מידע רשת

getprotobyname#

מחפש פרוטוקול IP לפי שמו הטקסטואלי ומחזיר את רשומת מסד הנתונים שלו.

getprotobyname היא עטיפת Perl סביב getprotobyname(3) של ספריית C של המערכת. בהינתן שם פרוטוקול כגון "tcp", "udp" או "icmp", היא מחזירה את הרשומה התואמת ממסד הנתונים /etc/protocols של המערכת (או מכל backend ש־nsswitch.conf מפנה אליו). השימוש האופייני הוא הפיכת שם פרוטוקול קריא־לאדם לערך המספרי ש־socket ו־setsockopt רוצים.

תקציר#

getprotobyname NAME
my ($name, $aliases, $proto) = getprotobyname NAME;
my $proto                    = getprotobyname NAME;   # scalar context

מה מקבלים בחזרה#

בהקשר רשימה, רשימה נראית־לארבעה־אלמנטים עם שלושה שדות:

my ($name, $aliases, $proto) = getprotobyname("tcp");
# $name    => canonical name, e.g. "tcp"
# $aliases => space-separated alias list, e.g. "TCP"
# $proto   => numeric protocol number, e.g. 6

בהקשר סקלר, רק המספר המספרי של הפרוטוקול ($proto). זו הצורה הנפוצה, מאחר שמספר הפרוטוקול הוא הסיבה המלאה שהחיפוש בוצע:

my $tcp = getprotobyname("tcp");   # 6

אם הפרוטוקול לא נמצא, ההחזרה היא רשימה ריקה בהקשר רשימה ו־undef בהקשר סקלר. תמיד בדוק מוגדרות לפני שימוש בתוצאה - 0 הוא מספר פרוטוקול תקף ("ip"), כך שבדיקת אמת בלבד אינה נכונה.

defined(my $tcp = getprotobyname("tcp"))
    or die "tcp protocol not in /etc/protocols";

מצב גלובלי שהוא נוגע בו#

  • חולק את סמן האיטרציה של מסד נתוני הפרוטוקולים עם getprotobynumber, getprotoent, setprotoent, ו־endprotoent. קריאה ל־getprotobyname עשויה למקם מחדש או לאפס את הסמן הזה בהתאם לספריית C של המערכת; אל תשלב חיפושים לפי שם עם לולאת איטרציה של getprotoent.

  • בחלק מהפלטפורמות getprotobyname(3) הבסיסי מגדיר את $! / errno בכישלון. קוד נייד אינו אמור להסתמך על כך - התייחס להחזרה לא־מוגדרת כ־״לא נמצא״ והמשך.

דוגמאות#

הפיכת שם למספר פרוטוקול עבור socket:

use Socket;
my $proto = getprotobyname("tcp")
    // die "tcp not configured";
socket(my $sock, PF_INET, SOCK_STREAM, $proto)
    or die "socket: $!";

צורת רשימה, כדי לראות את השם הקנוני וכינויים שמערכת משתמשת בהם:

my ($name, $aliases, $proto) = getprotobyname("TCP");
print "name=$name aliases=$aliases number=$proto\n";
# name=tcp aliases=TCP number=6

חיפוש הגנתי עם נפילה חזרה לשני הפרוטוקולים שכל סקריפט באמת זקוק להם:

my %num_for = (tcp => 6, udp => 17, icmp => 1);
sub proto_num {
    my ($name) = @_;
    return getprotobyname($name) // $num_for{lc $name};
}

הקשר סקלר נדרש כאשר ערך ההחזרה מזין ביטוי; הקשר רשימה היה משטח לתוך הרשימה הסובבת:

my @args = (SOCK_STREAM, scalar getprotobyname("tcp"));

מקרי קצה#

  • רגישות לאותיות גדולות וקטנות תלויה במערכת. getprotobyname(3) של glibc מתאים את השם הקנוני ואת כל הכינויים ללא רגישות לאותיות גדולות וקטנות; ספריות C אחרות עשויות שלא לעשות זאת. אם ניידות משנה, העבר את הצורה באותיות קטנות ("tcp", לא "TCP").

  • מספר פרוטוקול 0 הוא תקף ("ip"). השתמש ב־defined(...), לא באמת בוליאנית, בעת בדיקת הצלחה.

  • לא זהה למספר פורט. getprotobyname("http") מחזיר undef - "http" הוא שם שירות, לא פרוטוקול. השתמש ב־getservbyname לחיפושי שירותים.

  • מחרוזת כינויים ריקה היא נורמלית. לרשומות רבות אין כינויים; ערך ההחזרה השני הוא אז המחרוזת הריקה, לא undef.

  • תופעות לוואי של סמן האיטרציה. אם התוכנית שלך באמצע לולאת getprotoent, קריאה ל־getprotobyname עלולה לאפס את הסמן ולדלג על רשומות או לחזור עליהן. סיים את האיטרציה, או שמור מצב, לפני ביצוע חיפושים לפי שם.

  • בטיחות threads. קריאת C הבסיסית אינה בטוחה ל־threads בכל פלטפורמה - היא בדרך כלל משתמשת בbuffer סטטי לכל־תהליך. Perl עשוי להשתמש בצורה הריאנטרנטית getprotobyname_r כאשר זמינה, אך אל תניח זאת.

  • רשומת /etc/protocols חסרה. בקונטיינרים מינימליים מסד הנתונים עלול להיות חסר, ובמקרה זה כל קריאה מחזירה undef. בנה טבלאות פרוטוקולים לתוך הקוד שלך כאשר אין הבטחה שסביבת היעד תשלח מסד נתוני פרוטוקולים.

הבדלים מהמקור#

תאימות מלאה עם Perl 5.42 המקורי.

ראו גם#

  • getprotobynumber - החיפוש ההפוך; השתמש כאשר יש לך את הפרוטוקול המספרי ואתה רוצה את שמו

  • getprotoent - מבצע איטרציה על כל רשומה במסד נתוני הפרוטוקולים, רשומה אחת בכל פעם

  • setprotoent / endprotoent - שולטים בסמן האיטרציה המשותף עם פונקציה זו

  • getservbyname - החיפוש המקביל לשירותים (פורטים), לא פרוטוקולים; השניים מבולבלים לעתים קרובות

  • socket - הצרכן הרגיל של מספר הפרוטוקול המוחזר

  • Net::protoent - עטיפה מונחית־עצמים שמחזירה רשומה blessed עם accessors בעלי שם במקום רשימה מיקומית