מידע רשת

gethostbyaddr#

מחפש רשומת מארח לפי כתובת ה־IP הארוזה שלו.

gethostbyaddr מבצע חיפוש DNS הפוך: בהינתן כתובת בינארית ארוזה (ארבעה בתים עבור IPv4, שישה־עשר עבור IPv6) ומשפחת הכתובות התואמת, הוא קורא לשגרת ה־C של המערכת gethostbyaddr(3) ומחזיר את רשומת המארח. מקרה השימוש הטיפוסי - ״ממכונת מי הגיע החבילה הזו?״ - רוצה את הצורה בהקשר סקלר: שם מארח יחיד. הצורה בהקשר רשימה חושפת את ה־struct hostent המלא: שם קנוני, כינויים, משפחת כתובות, אורך כתובת, וכל כתובת שה־resolver יודע למארח הזה.

תקציר#

my $name = gethostbyaddr $packed_addr, $addrtype;
my ($name, $aliases, $addrtype, $length, @addrs) = gethostbyaddr $packed_addr, $addrtype;

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

הקשר סקלר - שם המארח הקנוני כמחרוזת רגילה, או undef אם החיפוש ההפוך נכשל.

הקשר רשימה - רשימה בת חמישה אלמנטים שמשקפת את struct hostent של C:

  • $name - שם המארח הקנוני שאליו ה־resolver מיפה את הכתובת.

  • $aliases - מחרוזת מופרדת ברווחים של שמות חלופיים. סקלר יחיד, לא רשימה.

  • $addrtype - משפחת הכתובות של הכתובות המוחזרות, בדרך כלל AF_INET (2) או AF_INET6 (10).

  • $length - אורך כל כתובת בבתים (4 עבור IPv4, 16 עבור IPv6).

  • @addrs - כל הכתובות שהוחזרו עבור המארח, כל אחת מחרוזת בינארית ארוזה באורך $length בתים. לעיתים קרובות אחת בלבד, אך מארחים multi-homed יכולים להניב כמה.

בכישלון חיפוש בהקשר רשימה, ההחזרה היא הרשימה הריקה.

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

  • $? - נקבע לערך h_errno של C בכישלון, כאשר הפלטפורמה חושפת אותו. יש לבדוק עם $? != 0 כדי להבחין בין HOST_NOT_FOUND ל־TRY_AGAIN ושגיאות חולפות דומות.

  • $! - אינו נקבע באופן משמעותי על־ידי כשלי DNS. חיפושים הפוכים נכשלים דרך h_errno, לא errno; אין לבדוק את $! לאחר קריאה שנכשלה.

  • סמן האיטרציה של מסד נתוני המארחים המשותף עם gethostent, sethostent, ו־endhostent. קריאה ל־gethostbyaddr עשויה לאפס סמן שנשאר פתוח על־ידי gethostent.

דוגמאות#

צורת סקלר - מיפוי dotted-quad לשם מארח:

use Socket;
my $packed = inet_aton("127.0.0.1");
my $name   = gethostbyaddr($packed, AF_INET);
print defined $name ? "$name\n" : "no PTR record\n";

נסיעה חזור - חיפוש קדימה, ואז חיפוש הפוך של הכתובת הראשונה:

use Socket;
my $packed = gethostbyname("www.perl.org");
my $name   = gethostbyaddr($packed, AF_INET);
print "$name\n";

זיהוי העמית בחיבור סוקט שהתקבל:

use Socket;
my $peer = getpeername($sock);
my ($port, $iaddr) = sockaddr_in($peer);
my $host = gethostbyaddr($iaddr, AF_INET);
printf "connection from %s:%d\n", $host // inet_ntoa($iaddr), $port;

צורת רשימה - כל שם וכתובת שה־resolver יודע על המארח:

use Socket;
my $packed = inet_aton("8.8.8.8");
my ($name, $aliases, $type, $len, @addrs) = gethostbyaddr($packed, AF_INET);
print "canonical: $name\n";
print "aliases:   $_\n" for split ' ', $aliases;
print "address:   ", inet_ntoa($_), "\n" for @addrs;

ממשק לפי־שם דרך העקיפה של Net::hostent - מתודות accessor במקום פריסה לפי מיקום:

use Net::hostent;
use Socket;
my $h = gethostbyaddr(inet_aton("127.0.0.1"), AF_INET);
print $h->name, "\n" if $h;

מקרי קצה#

  • ADDR הוא מחרוזת בינארית ארוזה, לא dotted-quad. העברת "127.0.0.1" ישירות לא עובדת - Perl יקרא ל־resolver עם תשעה בתים גולמיים ולא יקבל בחזרה שום דבר שימושי. יש לעבור תמיד דרך Socket::inet_aton, Socket::inet_pton, או packer שווה־ערך קודם.

  • ADDRTYPE חייב להתאים לרוחב הכתובת. AF_INET רוצה ADDR בן ארבעה בתים; AF_INET6 רוצה שישה־עשר. אי־התאמה מחזירה undef או, בפלטפורמות מסוימות, קוראת מעבר לבופר. יש להשתמש בקבוע מ־Socket, לא במספר שלם שהוקלד ביד.

  • יש לבדוק undef בצורת הסקלר. רשומת PTR חסרה מחזירה undef, לא מחרוזת ריקה. לכתובות רבות באינטרנט הציבורי אין מיפוי הפוך כלל.

  • @addrs עשויה לא לכלול את הכתובת שנשאלה. ה־resolver מחזיר את הרשומה המלאה עבור המארח הקנוני, שעשויה להכיל כתובות נוספות שבמקרה חולקות את שם המארח.

  • הקשר סקלר מריץ את קריאת ה־resolver המלאה בכל מקרה. שגרת ה־C תמיד ממלאת את כל ה־hostent; Perl פשוט משליך את הרשימה. אין יתרון ביצועים לצורת הסקלר מעבר לקוד ברור יותר.

  • היפוך של חיפוש קדימה אינו מובטח לנסיעה חזור. gethostbyaddr(gethostbyname($h), AF_INET) עשוי להחזיר שם שונה מ־$h - DNS הפוך ממפה לשם המארח הקנוני, ששונה לעיתים קרובות מהכינוי שהשתמש בשאילתה קדימה.

  • תמיכת IPv6 תלוית פלטפורמה. לא כל gethostbyaddr(3) של libc מטפל ב־AF_INET6 בנקיון. לפתרון הפוך נייד dual-stack יש להשתמש ב־Socket::getnameinfo.

  • בטיחות thread. שגרת ה־C הבסיסית שומרת מצב סטטי לכל־תהליך עבור סמן המארח. קריאות בו־זמניות מ־threads מרובים עשויות לשזור תוצאות. סקריפטים שדורשים פתרון הפוך בטוח־thread צריכים להשתמש ב־Socket::getnameinfo.

הבדלים מ־upstream#

תואם מלא ל־upstream Perl 5.42.

ראו גם#

  • gethostbyname - החיפוש קדימה: שם מארח → כתובת ארוזה

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

  • sethostent - להחזיר את המצביע של איטרטור המארחים ולשלוט האם הקובץ נשאר פתוח בין חיפושים

  • Socket::inet_aton - לבנות את ארגומנט ה־ADDR הארוז ממחרוזת dotted-quad

  • Socket::inet_ntoa - לעבד כתובת ארוזה מתוך @addrs חזרה לצורת dotted-quad

  • Socket::getnameinfo - resolver הפוך מודרני, אגנוסטי לפרוטוקול, שמטפל ב־IPv6 ובטוח־thread