📄 route.c
字号:
} if (forcehost) ishost = 1; if (forcenet) ishost = 0; flags |= RTF_UP; if (ishost) flags |= RTF_HOST; if (iflag == 0) flags |= RTF_GATEWAY; for (attempts = 1; ; attempts++) { errno = 0; if (Cflag && (af == AF_INET || af == AF_NS)) { route.rt_flags = flags; route.rt_dst = so_dst.sa; route.rt_gateway = so_gate.sa; if ((ret = ioctl(s, *cmd == 'a' ? SIOCADDRT : SIOCDELRT, (caddr_t)&route)) == 0) break; } else { if ((ret = rtmsg(*cmd, flags)) == 0) break; } if (errno != ENETUNREACH && errno != ESRCH) break; if (af == AF_INET && hp && hp->h_addr_list[1]) { hp->h_addr_list++; bcopy(hp->h_addr_list[0], (caddr_t)&so_dst.sin.sin_addr, hp->h_length); } else break; } if (*cmd == 'g') exit(0); oerrno = errno; (void) printf("%s %s %s: gateway %s", cmd, ishost? "host" : "net", dest, gateway); if (attempts > 1 && ret == 0) (void) printf(" (%s)", inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr)); if (ret == 0) (void) printf("\n"); else { switch (oerrno) { case ESRCH: err = "not in table"; break; case EBUSY: err = "entry in use"; break; case ENOBUFS: err = "routing table overflow"; break; default: err = strerror(oerrno); break; } (void) printf(": %s\n", err); }}voidinet_makenetandmask(net, sin) u_long net; register struct sockaddr_in *sin;{ u_long addr, mask = 0; register char *cp; rtm_addrs |= RTA_NETMASK; if (net == 0) mask = addr = 0; else if (net < 128) { addr = net << IN_CLASSA_NSHIFT; mask = IN_CLASSA_NET; } else if (net < 65536) { addr = net << IN_CLASSB_NSHIFT; mask = IN_CLASSB_NET; } else if (net < 16777216L) { addr = net << IN_CLASSC_NSHIFT; mask = IN_CLASSC_NET; } else { addr = net; if ((addr & IN_CLASSA_HOST) == 0) mask = IN_CLASSA_NET; else if ((addr & IN_CLASSB_HOST) == 0) mask = IN_CLASSB_NET; else if ((addr & IN_CLASSC_HOST) == 0) mask = IN_CLASSC_NET; else mask = -1; } sin->sin_addr.s_addr = htonl(addr); sin = &so_mask.sin; sin->sin_addr.s_addr = htonl(mask); sin->sin_len = 0; sin->sin_family = 0; cp = (char *)(&sin->sin_addr + 1); while (*--cp == 0 && cp > (char *)sin) ; sin->sin_len = 1 + cp - (char *)sin;}/* * Interpret an argument as a network address of some kind, * returning 1 if a host address, 0 if a network address. */intgetaddr(which, s, hpp) int which; char *s; struct hostent **hpp;{ register sup su; struct ns_addr ns_addr(); struct iso_addr *iso_addr(); struct hostent *hp; struct netent *np; u_long val; if (af == 0) { af = AF_INET; aflen = sizeof(struct sockaddr_in); } rtm_addrs |= which; switch (which) { case RTA_DST: su = so_addrs[0]; su->sa.sa_family = af; break; case RTA_GATEWAY: su = so_addrs[1]; su->sa.sa_family = af; break; case RTA_NETMASK: su = so_addrs[2]; break; case RTA_GENMASK: su = so_addrs[3]; break; case RTA_IFP: su = so_addrs[4]; su->sa.sa_family = af; break; case RTA_IFA: su = so_addrs[5]; su->sa.sa_family = af; break; default: usage("Internal Error"); /*NOTREACHED*/ } su->sa.sa_len = aflen; if (strcmp(s, "default") == 0) { switch (which) { case RTA_DST: forcenet++; (void) getaddr(RTA_NETMASK, s, 0); break; case RTA_NETMASK: case RTA_GENMASK: su->sa.sa_len = 0; } return 0; } if (af == AF_NS) goto do_xns; if (af == AF_OSI) goto do_osi; if (af == AF_LINK) goto do_link; if (af == AF_CCITT) goto do_ccitt; if (af == 0) goto do_sa; if (hpp == NULL) hpp = &hp; *hpp = NULL; if (((val = inet_addr(s)) != -1) && (which != RTA_DST || forcenet == 0)) { su->sin.sin_addr.s_addr = val; if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY) return (1); else { val = ntohl(val); out: if (which == RTA_DST) inet_makenetandmask(val, &su->sin); return (0); } } val = inet_network(s); if (val != -1) { goto out; } np = getnetbyname(s); if (np) { val = np->n_net; goto out; } hp = gethostbyname(s); if (hp) { *hpp = hp; su->sin.sin_family = hp->h_addrtype; bcopy(hp->h_addr, (char *)&su->sin.sin_addr, hp->h_length); return (1); } (void) fprintf(stderr, "%s: bad value\n", s); exit(1);do_xns: if (which == RTA_DST) { extern short ns_bh[3]; struct sockaddr_ns *sms = &(so_mask.sns); bzero((char *)sms, sizeof(*sms)); sms->sns_family = 0; sms->sns_len = 6; sms->sns_addr.x_net = *(union ns_net *)ns_bh; rtm_addrs |= RTA_NETMASK; } su->sns.sns_addr = ns_addr(s); return (!ns_nullhost(su->sns.sns_addr));do_osi: su->siso.siso_addr = *iso_addr(s); if (which == RTA_NETMASK || which == RTA_GENMASK) { register char *cp = (char *)TSEL(&su->siso); su->siso.siso_nlen = 0; do {--cp ;} while ((cp > (char *)su) && (*cp == 0)); su->siso.siso_len = 1 + cp - (char *)su; } return (1);do_ccitt: ccitt_addr(s, &su->sx25); return (1);do_link: link_addr(s, &su->sdl); return (1);do_sa: su->sa.sa_len = sizeof(*su); sockaddr(s, &su->sa); return (1);}short ns_nullh[] = {0,0,0};short ns_bh[] = {-1,-1,-1};char *ns_print(sns) struct sockaddr_ns *sns;{ struct ns_addr work; union { union ns_net net_e; u_long long_e; } net; u_short port; static char mybuf[50], cport[10], chost[25]; char *host = ""; register char *p; register u_char *q; work = sns->sns_addr; port = ntohs(work.x_port); work.x_port = 0; net.net_e = work.x_net; if (ns_nullhost(work) && net.long_e == 0) { if (!port) return ("*.*"); (void) sprintf(mybuf, "*.%XH", port); return (mybuf); } if (bcmp((char *)ns_bh, (char *)work.x_host.c_host, 6) == 0) host = "any"; else if (bcmp((char *)ns_nullh, (char *)work.x_host.c_host, 6) == 0) host = "*"; else { q = work.x_host.c_host; (void) sprintf(chost, "%02X%02X%02X%02X%02X%02XH", q[0], q[1], q[2], q[3], q[4], q[5]); for (p = chost; *p == '0' && p < chost + 12; p++) /* void */; host = p; } if (port) (void) sprintf(cport, ".%XH", htons(port)); else *cport = 0; (void) sprintf(mybuf,"%XH.%s%s", ntohl(net.long_e), host, cport); return (mybuf);}voidmonitor(){ int n; char msg[2048]; verbose = 1; for(;;) { n = read(s, msg, 2048); (void) printf("got message of size %d\n", n); print_rtmsg((struct rt_msghdr *)msg); }}struct { struct rt_msghdr m_rtm; char m_space[512];} m_rtmsg;intrtmsg(cmd, flags) int cmd, flags;{ static int seq; int rlen; register char *cp = m_rtmsg.m_space; register int l;#define NEXTADDR(w, u) \ if (rtm_addrs & (w)) {\ l = ROUNDUP(u.sa.sa_len); bcopy((char *)&(u), cp, l); cp += l;\ if (verbose) sodump(&(u),"u");\ } errno = 0; bzero((char *)&m_rtmsg, sizeof(m_rtmsg)); if (cmd == 'a') cmd = RTM_ADD; else if (cmd == 'c') cmd = RTM_CHANGE; else if (cmd == 'g') cmd = RTM_GET; else cmd = RTM_DELETE;#define rtm m_rtmsg.m_rtm rtm.rtm_type = cmd; rtm.rtm_flags = flags; rtm.rtm_version = RTM_VERSION; rtm.rtm_seq = ++seq; rtm.rtm_addrs = rtm_addrs; rtm.rtm_rmx = rt_metrics; rtm.rtm_inits = rtm_inits; if (rtm_addrs & RTA_NETMASK) mask_addr(); NEXTADDR(RTA_DST, so_dst); NEXTADDR(RTA_GATEWAY, so_gate); NEXTADDR(RTA_NETMASK, so_mask); NEXTADDR(RTA_GENMASK, so_genmask); NEXTADDR(RTA_IFP, so_ifp); NEXTADDR(RTA_IFA, so_ifa); rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; if (verbose) print_rtmsg(&rtm, l); if (debugonly) return 0; if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { perror("writing to routing socket"); return (-1); } if (cmd == RTM_GET) { do { l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); if (l < 0) (void) fprintf(stderr, "route: read from routing socket: %s\n", strerror(errno)); else print_getmsg(&rtm, l); }#undef rtm return (0);}mask_addr() { register char *cp1, *cp2; int olen; if ((rtm_addrs & RTA_DST) == 0) return; switch(so_dst.sa.sa_family) { case AF_NS: case AF_INET: case 0: return; case AF_ISO: olen = MIN(so_dst.siso.siso_nlen, so_mask.sa.sa_len - 6); } cp1 = so_mask.sa.sa_len + 1 + (char *)&so_dst; cp2 = so_dst.sa.sa_len + 1 + (char *)&so_dst; while (cp2 > cp1) *--cp2 = 0; cp2 = so_mask.sa.sa_len + 1 + (char *)&so_mask; while (cp1 > so_dst.sa.sa_data) *--cp1 &= *--cp2; switch(so_dst.sa.sa_family) { case AF_ISO: so_dst.siso.siso_nlen = olen; }}char *msgtypes[] = { "", "RTM_ADD: Add Route", "RTM_DELETE: Delete Route", "RTM_CHANGE: Change Metrics or flags", "RTM_GET: Report Metrics", "RTM_LOSING: Kernel Suspects Partitioning", "RTM_REDIRECT: Told to use different route", "RTM_MISS: Lookup failed on this address", "RTM_LOCK: fix specified metrics", "RTM_OLDADD: caused by SIOCADDRT", "RTM_OLDDEL: caused by SIOCDELRT", 0,};char metricnames[] ="\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu";char routeflags[] = "\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CLONING\012XRESOLVE\013LLINFO\017PROTO2\020PROTO1";voidprint_rtmsg(rtm, msglen) register struct rt_msghdr *rtm; int msglen;{ if (verbose == 0) return; if (rtm->rtm_version != RTM_VERSION) { (void) printf("routing message version %d not understood\n", rtm->rtm_version); return; } (void) printf("%s\npid: %d, len %d, seq %d, errno %d, flags:", msgtypes[rtm->rtm_type], rtm->rtm_pid, rtm->rtm_msglen, rtm->rtm_seq, rtm->rtm_errno); bprintf(stdout, rtm->rtm_flags, routeflags); pmsg_common(rtm);}voidprint_getmsg(rtm, msglen) register struct rt_msghdr *rtm; int msglen;{ if (rtm->rtm_version != RTM_VERSION) { (void)printf("routing message version %d not understood\n", rtm->rtm_version); return; } if (rtm->rtm_msglen > msglen) { (void)printf("get length mismatch, in packet %d, returned %d\n", rtm->rtm_msglen, msglen); } (void) printf("RTM_GET: errno %d, flags:", rtm->rtm_errno); bprintf(stdout, rtm->rtm_flags, routeflags); (void) printf("\nmetric values:\n ");#define metric(f, e)\ printf("%s: %d%s", __STRING(f), rtm->rtm_rmx.__CONCAT(rmx_,f), e) metric(recvpipe, ", "); metric(sendpipe, ", "); metric(ssthresh, ", "); metric(rtt, "\n "); metric(rttvar, ", "); metric(hopcount, ", "); metric(mtu, ", "); metric(expire, "\n");#undef metric pmsg_common(rtm);}voidpmsg_common(rtm) register struct rt_msghdr *rtm;{ char *cp; register struct sockaddr *sa; int i; (void) printf("\nlocks: "); bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames); (void) printf(" inits: "); bprintf(stdout, rtm->rtm_inits, metricnames); (void) printf("\nsockaddrs: "); bprintf(stdout, rtm->rtm_addrs, "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR"); (void) putchar('\n'); cp = ((char *)(rtm + 1)); if (rtm->rtm_addrs) for (i = 1; i; i <<= 1) if (i & rtm->rtm_addrs) { sa = (struct sockaddr *)cp; (void) printf(" %s", routename(sa)); ADVANCE(cp, sa); } (void) putchar('\n'); (void) fflush(stdout);}voidbprintf(fp, b, s) register FILE *fp; register int b; register u_char *s;{ register int i; int gotsome = 0; if (b == 0) return; while (i = *s++) { if (b & (1 << (i-1))) { if (gotsome == 0) i = '<'; else i = ','; (void) putc(i, fp); gotsome = 1; for (; (i = *s) > 32; s++) (void) putc(i, fp); } else while (*s > 32) s++; } if (gotsome) (void) putc('>', fp);}intkeyword(cp) char *cp;{ register struct keytab *kt = keywords; while (kt->kt_cp && strcmp(kt->kt_cp, cp)) kt++; return kt->kt_i;}voidsodump(su, which) register sup su; char *which;{ switch (su->sa.sa_family) { case AF_LINK: (void) printf("%s: link %s; ", which, link_ntoa(&su->sdl)); break; case AF_ISO: (void) printf("%s: iso %s; ", which, iso_ntoa(&su->siso.siso_addr)); break; case AF_INET: (void) printf("%s: inet %s; ", which, inet_ntoa(su->sin.sin_addr)); break; case AF_NS: (void) printf("%s: xns %s; ", which, ns_ntoa(su->sns.sns_addr)); break; } (void) fflush(stdout);}/* States*/#define VIRGIN 0#define GOTONE 1#define GOTTWO 2/* Inputs */#define DIGIT (4*0)#define END (4*1)#define DELIM (4*2)voidsockaddr(addr, sa)register char *addr;register struct sockaddr *sa;{ register char *cp = (char *)sa; int size = sa->sa_len; char *cplim = cp + size; register int byte = 0, state = VIRGIN, new; bzero(cp, size); do { if ((*addr >= '0') && (*addr <= '9')) { new = *addr - '0'; } else if ((*addr >= 'a') && (*addr <= 'f')) { new = *addr - 'a' + 10; } else if ((*addr >= 'A') && (*addr <= 'F')) { new = *addr - 'A' + 10; } else if (*addr == 0) state |= END; else state |= DELIM; addr++; switch (state /* | INPUT */) { case GOTTWO | DIGIT: *cp++ = byte; /*FALLTHROUGH*/ case VIRGIN | DIGIT: state = GOTONE; byte = new; continue; case GOTONE | DIGIT: state = GOTTWO; byte = new + (byte << 4); continue; default: /* | DELIM */ state = VIRGIN; *cp++ = byte; byte = 0; continue; case GOTONE | END: case GOTTWO | END: *cp++ = byte; /* FALLTHROUGH */ case VIRGIN | END: break; } break; } while (cp < cplim); sa->sa_len = cp - (char *)sa;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -