/* * Copyright 2024 VMS Software, Inc. * M. Zaharee 2/2/2024 */ #define _SOCKADDR_LEN #include #include #include #include #include #include #include #include #include #include // not presently distributed by crtl. #include "if_dl.h" struct value_string_map { int value; char *string; }; int get_addr(void); int main(int argc, char * *argv) { int status; status = get_addr(); } char * map_value_to_string(int value, struct value_string_map *string_map ) { struct value_string_map *p = string_map; while (p->string) { if (value == p->value) { return p->string; } p++; } return (char *) NULL; } char * map_sdl_type_to_string(int type) { static struct value_string_map sdl_type_map[] = { { IFT_ETHER, "IFT_ETHER" }, { IFT_LAG, "IFT_LAG" }, { IFT_VLAN, "IFT_VLAN" }, { IFT_FDDI, "IFT_FDDI" }, { IFT_LOOP, "IFT_LOOP" }, { IFT_OTHER, "IFT_OTHER" }, { IFT_IP624, "IFT_IP624" }, { 0, NULL } }; return map_value_to_string(type, sdl_type_map); } int get_addr(void) { struct ifreq *ifr; struct ifconf ifc; struct sockaddr *sa; int s; u_char *reqbuf; int needed_for_ifreq; int advancing; char buffer[80]; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { perror("get_addr socket"); return 0; } // Determine the memory requirements for the ifreq structures which will // be returned. ifc.ifc_buf = 0; ifc.ifc_len = 0; if ((ioctl(s, SIOCGIFCONF, (caddr_t)&ifc ) == 0) && (ifc.ifc_len != 0)) { // ifconfig contains this code which doubles the returned memory // requirement value. The question is why? The only thing which // comes to mind is the amount of memory needed for request could // change in between asking how much memory is needed and making // the call which actually returns the data. Sure, let's go with // that. needed_for_ifreq = 2 * ifc.ifc_len; } else { fprintf(stderr, "getaddr(): ioctl failed, cannot determine memory requirements\n"); close (s); return (0); } // Allocate and zero required memory ... if ((reqbuf = (u_char *)malloc(needed_for_ifreq)) == NULL) { fprintf(stderr, "getaddr(): cannot allocate memory for request\n"); close (s); return 0; } bzero(reqbuf, needed_for_ifreq); // Fill in buffer details ... ifc.ifc_buf = (caddr_t) reqbuf; ifc.ifc_len = needed_for_ifreq; // Now, request the information if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { fprintf(stderr, "get_addr(): ioctl failure, cannot retrieve interface data\n"); close(s); free(reqbuf); return 0; } ifr = (struct ifreq *)ifc.ifc_req; while((u_char *)ifr < (u_char *)(reqbuf + ifc.ifc_len)) { sa = &ifr->ifr_addr; switch (sa->sa_family) { case AF_INET: { struct sockaddr_in *sinp; sinp = (struct sockaddr_in *) sa; inet_ntop(AF_INET, &sinp->sin_addr, buffer, sizeof(buffer)); fprintf(stdout, "interface %s, AF_INET address %s\n\n", ifr->ifr_name, buffer); break; } case AF_INET6: { struct sockaddr_in6 *sin6p; sin6p = (struct sockaddr_in6 *) sa; inet_ntop(AF_INET6, &sin6p->sin6_addr, buffer, sizeof(buffer)); fprintf(stdout, "interface %s, AF_INET6 address %s\n\n", ifr->ifr_name, buffer); break; } case AF_LINK: { struct sockaddr_dl *sdlp; sdlp = (struct sockaddr_dl *) sa; char *sdl_type_string = map_sdl_type_to_string(sdlp->sdl_type); switch (sdlp->sdl_type) { case IFT_ETHER: case IFT_LAG: case IFT_VLAN: case IFT_FDDI: { u_char *p = (u_char *) &sdlp->sdl_data[sdlp->sdl_nlen]; fprintf(stdout, "interface %s, AF_LINK type %s address %02x:%02x:%02x:%02x:%02x:%02x\n\n", ifr->ifr_name, sdl_type_string, p[0], p[1], p[2], p[3], p[4], p[5]); break; } case IFT_LOOP: case IFT_OTHER: case IFT_IP624: { fprintf(stdout, "interface %s, AF_LINK type %s (no address)\n\n", ifr->ifr_name, sdl_type_string); if (sdlp->sdl_alen != 0) { fprintf(stderr, "Warning: sdl_alen should be 0, but is %d!\n", sdlp->sdl_alen); } break; } default: { fprintf(stdout, "interface %s, AF_LINK type 0x%x decode not supported.\n", ifr->ifr_name, sdlp->sdl_type); fprintf(stdout, "AF_LINK ifreq nlen: %d, alen: %d, slen: %d\n\n", sdlp->sdl_nlen, sdlp->sdl_alen, sdlp->sdl_slen); break; } } } } // // Based on size of current ifreq, determine where next one starts. // advancing = sa->sa_len > sizeof(*sa)? (sa->sa_len - sizeof(*sa)) : 0; ifr = (struct ifreq *)((char *)ifr + sizeof(*ifr) + advancing); #if 0 fprintf(stderr, "advanced based on %d additional bytes (sa_family = %d)\n", advancing, sa->sa_family); #endif } return 1; }