int main(int argc, char *argv[]) { int sockfd; char *buf; pid_t pid; ssize_t n; struct rt_msghdr *rtm; struct sockaddr *sa, *rti_info[RTAX_MAX]; struct sockaddr_in *sin; if (argc != 2) err_quit("Usage: %s <IPaddress>", basename(argv[0])); sockfd = Socket(AF_ROUTE, SOCK_RAW, 0); /* need superuser privileges */ buf = Calloc(1, BUFLEN); /* and initialized to 0 */ rtm = (struct rt_msghdr *)buf; rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in); rtm->rtm_version = RTM_VERSION; rtm->rtm_type = RTM_GET; rtm->rtm_addrs = RTA_DST; rtm->rtm_pid = pid = getpid(); rtm->rtm_seq = SEQ; sin = (struct sockaddr_in *)(rtm + 1); sin->sin_len = sizeof(struct sockaddr_in); sin->sin_family = AF_INET; Inet_pton(AF_INET, argv[1], &sin->sin_addr); Write(sockfd, rtm, rtm->rtm_msglen); do { n = Read(sockfd, rtm, BUFLEN); } while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ || rtm->rtm_pid != pid); rtm = (struct rt_msghdr *)buf; sa = (struct sockaddr *)(rtm + 1); get_rtaddrs(rtm->rtm_addrs, sa, rti_info); if ((sa = rti_info[RTAX_DST]) != NULL) printf("dest: %s\n", Sock_ntop_host(sa, sa->sa_len)); if ((sa = rti_info[RTAX_GATEWAY]) != NULL) printf("gateway: %s\n", Sock_ntop_host(sa, sa->sa_len)); if ((sa = rti_info[RTAX_NETMASK]) != NULL) printf("netmask: %s\n", sock_masktop(sa, sa->sa_len)); if ((sa = rti_info[RTAX_GENMASK]) != NULL) printf("genmask: %s\n", sock_masktop(sa, sa->sa_len)); exit(0); }
// function used to configure a route to "daddr" by specifying either // the gateway address "gaddr" or the interface name "ifname"; // a mask given by "maddr" can also be specified // the command codes "cmd" indicate the type of operation // Note: addresses are given as 4-byte words (c.f. rtctl) int rtctl2(uint32_t *daddr, /* destination IP address */ uint32_t *gaddr, /* gateway IP address */ uint32_t *maddr, /* subnet mask */ char *ifname, /* network interface name */ u_char cmd) /* RTM_ADD RTM_DELETE RTM_CHANGE */ { int sockfd, mib[6], len; char *buf, rta_cmd[RTCTL_CMD_LEN], *ifbuf; char dstaddr[16], gateaddr[16], maskaddr[16]; u_char flag; pid_t pid; struct rt_msghdr *rtm; struct sockaddr_in *dst, *gate, *mask; struct sockaddr_dl *ifp, *sdl; struct if_msghdr *ifm; #ifdef RTCTL_PRINT_RESPONSE ssize_t n; struct sockaddr *sa, *rti_info[RTAX_MAX]; #endif /* check the arguments */ if (daddr == NULL) { fprintf(stderr, "Invalid destination IP address\n"); return -1; } flag = 0; if (cmd == RTM_ADD) { flag |= RTCTL_ADD; strncpy(rta_cmd, "add", sizeof("add")); if (gaddr == NULL) { if (ifname == NULL) flag |= RTCTL_UNKNOWN; else if (maddr != NULL) flag |= RTCTL_UNKNOWN; else flag |= RTCTL_IF; } else { flag |= RTCTL_GATEWAY; if (ifname != NULL) flag |= RTCTL_UNKNOWN; else if (maddr != NULL) flag |= RTCTL_NETMASK; } } else if (cmd == RTM_DELETE) { flag |= RTCTL_DELETE; strncpy(rta_cmd, "delete", sizeof("delete")); if ((ifname != NULL) | (gaddr != NULL) | (maddr != NULL)) flag |= RTCTL_UNKNOWN; } else if (cmd == RTM_CHANGE) { flag |= RTCTL_CHANGE; strncpy(rta_cmd, "change", sizeof("change")); if (gaddr == NULL) { if (ifname == NULL) flag |= RTCTL_UNKNOWN; else if (maddr != NULL) flag |= RTCTL_UNKNOWN; else flag |= RTCTL_IF; } else { flag |= RTCTL_GATEWAY; if (ifname != NULL) flag |= RTCTL_UNKNOWN; else if (maddr != NULL) flag |= RTCTL_NETMASK; } } else { fprintf(stderr, "Invalid command name\n"); return -1; } if (flag & RTCTL_UNKNOWN) { fprintf(stderr, "Unknown arguments are inputed.\n"); return -1; } if ((buf = calloc(1, BUFLEN)) == NULL) { perror("calloc"); return -1; } /* set address of rt messages */ rtm = (struct rt_msghdr *) buf; rtm->rtm_version = RTM_VERSION; rtm->rtm_type = cmd; rtm->rtm_pid = pid = getpid(); rtm->rtm_seq = ++rtm_seq; rtm->rtm_errno = 0; if ((flag & RTCTL_ADD) | (flag & RTCTL_CHANGE)) { if (flag & RTCTL_IF) { rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in) + sizeof(struct sockaddr_dl); rtm->rtm_addrs = RTA_DST | RTA_GATEWAY; rtm->rtm_flags = RTF_UP | RTF_HOST | RTF_LLINFO | RTF_STATIC; } else if (flag & RTCTL_NETMASK) { rtm->rtm_msglen = sizeof(struct rt_msghdr) + 3 * sizeof(struct sockaddr_in); rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; rtm->rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; } else { rtm->rtm_msglen = sizeof(struct rt_msghdr) + 2 * sizeof(struct sockaddr_in); rtm->rtm_addrs = RTA_DST | RTA_GATEWAY; rtm->rtm_flags = RTF_UP | RTF_HOST | RTF_GATEWAY | RTF_STATIC; } } else if (flag & RTCTL_DELETE) { rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in); rtm->rtm_addrs = RTA_DST; } /* set destination RTA_GATEWAY */ dst = (struct sockaddr_in *) (rtm + 1); dst->sin_len = sizeof(struct sockaddr_in); dst->sin_family = AF_INET; fflush(stderr); dst->sin_addr.s_addr = *daddr; if (flag & RTCTL_GATEWAY) { /* set gateway */ gate = (struct sockaddr_in *) (dst + 1); gate->sin_len = sizeof(struct sockaddr_in); gate->sin_family = AF_INET; gate->sin_addr.s_addr = *gaddr; if (flag & RTCTL_NETMASK) { mask = (struct sockaddr_in *) (gate + 1); mask->sin_len = sizeof(struct sockaddr_in); mask->sin_family = AF_INET; mask->sin_addr.s_addr = *maddr; } } else if (flag & RTCTL_IF) { /* get sockaddr_dl info */ mib[0] = CTL_NET; mib[1] = AF_ROUTE; mib[2] = 0; mib[3] = AF_LINK; mib[4] = NET_RT_IFLIST; if ((mib[5] = if_nametoindex(ifname)) == 0) { perror("if_nametoindex"); return -1; } if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { perror("sysctl"); return -1; } if ((ifbuf = calloc(1, len)) == NULL) { perror("calloc"); return -1; } if (sysctl(mib, 6, ifbuf, &len, NULL, 0) < 0) { perror("sysctl2"); return -1; } ifm = (struct if_msghdr *) ifbuf; sdl = (struct sockaddr_dl *) (ifm + 1); /* set network interface */ ifp = (struct sockaddr_dl *) (dst + 1); bcopy(sdl, ifp, sizeof(struct sockaddr_dl)); ifp->sdl_len = sizeof(struct sockaddr_dl); } if ((sockfd = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) { perror("socket"); return -1; } if (write(sockfd, rtm, rtm->rtm_msglen) < 0) { perror("write"); //return -1; } else { strncpy(dstaddr, "", sizeof(dstaddr)); strncpy(gateaddr, "", sizeof(gateaddr)); strncpy(maskaddr, "", sizeof(maskaddr)); strncpy(dstaddr, inet_ntoa(dst->sin_addr), sizeof(dstaddr)); if (gaddr != NULL) strncpy(gateaddr, inet_ntoa(gate->sin_addr), sizeof(gateaddr)); if (maddr != NULL) strncpy(maskaddr, inet_ntoa(mask->sin_addr), sizeof(maskaddr)); fprintf(stderr, "\troute %s dst:%s gate:%s mask:%s ifp:%s\n", rta_cmd, dstaddr, gateaddr, maskaddr, ifname); /* A chunk of lines like this: */ /* strncpy(dstaddr, "", sizeof(dstaddr)); */ /* strncpy(gateaddr, "", sizeof(gateaddr)); */ /* strncpy(maskaddr, "", sizeof(maskaddr)); */ /* strncpy(dstaddr, inet_ntoa(dst->sin_addr), sizeof(dstaddr)); */ /* if (gaddr != NULL) */ /* strncpy(gateaddr, inet_ntoa(gate->sin_addr), */ /* sizeof(gateaddr)); */ /* if (maddr != NULL) */ /* strncpy(maskaddr, inet_ntoa(mask->sin_addr), */ /* sizeof(maskaddr)); */ /* fprintf(stderr, "\troute %s dst:%s gate:%s mask:%s ifp:%s\n", */ /* rta_cmd, dstaddr, gateaddr, maskaddr, ifname); */ /* can be rewritten as: */ /* fprintf(stderr, "\troute %s dst:%s gate:%s ", rta_cmd, dstaddr, */ /* (gaddr != NULL) : inet_ntoa(gate->sin_addr) ? ""); */ /* fprintf(stderr, "mask:%s ifp:%s\n", */ /* (maddr != NULL) : inet_ntoa(mask->sin_addr) ? "", ifname); */ } #ifdef RTCTL_PRINT_RESPONSE fprintf(stderr, "---print response\n"); do { n = read(sockfd, rtm, BUFLEN); } while (rtm->rtm_seq != rtm_seq || rtm->rtm_pid != pid); /* handle response */ rtm = (struct rt_msghdr *) buf; sa = (struct sockaddr *) (rtm + 1); get_rtaddrs(rtm->rtm_addrs, sa, rti_info); if ((sa = rti_info[RTAX_DST]) != NULL) fprintf(stderr, "dest: %s\n", sock_ntop_host(sa, sa->sa_len)); if ((sa = rti_info[RTAX_GATEWAY]) != NULL) fprintf(stderr, "gateway: %s\n", sock_ntop_host(sa, sa->sa_len)); if ((sa = rti_info[RTAX_NETMASK]) != NULL) fprintf(stderr, "netmask: %s\n", sock_masktop(sa, sa->sa_len)); if ((sa = rti_info[RTAX_GENMASK]) != NULL) fprintf(stderr, "genmask: %s\n", sock_masktop(sa, sa->sa_len)); if ((sa = rti_info[RTAX_IFP]) != NULL) fprintf(stderr, "ifp: len:%d fami:%d data:%s\n", sa->sa_len, sa->sa_family, sa->sa_data); if ((sa = rti_info[RTAX_IFA]) != NULL) fprintf(stderr, "ifa: len:%d fami:%d data:%s\n", sa->sa_len, sa->sa_family, sa->sa_data); if ((sa = rti_info[RTAX_AUTHOR]) != NULL) fprintf(stderr, "author: len:%d fami:%d data:%s\n", sa->sa_len, sa->sa_family, sa->sa_data); if ((sa = rti_info[RTAX_BRD]) != NULL) fprintf(stderr, "brd: len:%d fami:%d data:%s\n", sa->sa_len, sa->sa_family, sa->sa_data); #endif free(buf); if (flag & RTCTL_IF) free(ifbuf); return 0; }
int getrt(char *ipaddr) { int sockfd; char *buf; pid_t pid; ssize_t n; struct rt_msghdr *rtm; struct sockaddr *sa, *rti_info[RTAX_MAX]; struct sockaddr_in *sin; if (ipaddr == NULL) { fprintf(stderr, "getrt: IP address.\n"); return -1; } if ((sockfd = socket(AF_ROUTE, SOCK_RAW, 0)) < 0) { perror("socket"); return -1; } buf = calloc(1, BUFLEN); rtm = (struct rt_msghdr *) buf; rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in); rtm->rtm_version = RTM_VERSION; rtm->rtm_type = RTM_GET; rtm->rtm_addrs = RTA_DST; rtm->rtm_pid = pid = getpid(); rtm->rtm_seq = SEQ; sin = (struct sockaddr_in *) (rtm + 1); sin->sin_len = sizeof(struct sockaddr_in); sin->sin_family = AF_INET; inet_pton(AF_INET, ipaddr, &sin->sin_addr); if (write(sockfd, rtm, rtm->rtm_msglen) < 0) { perror("write"); exit(1); } do { n = read(sockfd, rtm, BUFLEN); } while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ || rtm->rtm_pid != pid); /* handle response */ rtm = (struct rt_msghdr *) buf; sa = (struct sockaddr *) (rtm + 1); get_rtaddrs(rtm->rtm_addrs, sa, rti_info); if ((sa = rti_info[RTAX_DST]) != NULL) fprintf(stderr, "dest: %s\n", sock_ntop_host(sa, sa->sa_len)); if ((sa = rti_info[RTAX_GATEWAY]) != NULL) fprintf(stderr, "gateway: %s\n", sock_ntop_host(sa, sa->sa_len)); if ((sa = rti_info[RTAX_NETMASK]) != NULL) fprintf(stderr, "netmask: %s\n", sock_masktop(sa, sa->sa_len)); if ((sa = rti_info[RTAX_GENMASK]) != NULL) fprintf(stderr, "genmask: %s\n", sock_masktop(sa, sa->sa_len)); if ((sa = rti_info[RTAX_IFP]) != NULL) fprintf(stderr, "ifp: len:%d fami:%d data:%s\n", sa->sa_len, sa->sa_family, sa->sa_data); if ((sa = rti_info[RTAX_IFA]) != NULL) fprintf(stderr, "ifa: len:%d fami:%d data:%s\n", sa->sa_len, sa->sa_family, sa->sa_data); return 0; }