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 בעלי שם במקום רשימה מיקומית