| 933 | } |
| 934 | |
| 935 | static int |
| 936 | rtmsg(int cmd) |
| 937 | { |
| 938 | static int seq; |
| 939 | int rlen; |
| 940 | register struct rt_msghdr *rtm = &m_rtmsg.m_rtm; |
| 941 | register char *cp = m_rtmsg.m_space; |
| 942 | register int l; |
| 943 | |
| 944 | errno = 0; |
| 945 | if (cmd == RTM_DELETE) |
| 946 | goto doit; |
| 947 | bzero((char *)&m_rtmsg, sizeof(m_rtmsg)); |
| 948 | rtm->rtm_flags = flags; |
| 949 | rtm->rtm_version = RTM_VERSION; |
| 950 | |
| 951 | switch (cmd) { |
| 952 | default: |
| 953 | fprintf(stderr, "ndp: internal wrong cmd\n"); |
| 954 | exit(1); |
| 955 | case RTM_ADD: |
| 956 | rtm->rtm_addrs |= RTA_GATEWAY; |
| 957 | if (expire_time) { |
| 958 | rtm->rtm_rmx.rmx_expire = expire_time; |
| 959 | rtm->rtm_inits = RTV_EXPIRE; |
| 960 | } |
| 961 | rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA); |
| 962 | /* FALLTHROUGH */ |
| 963 | case RTM_GET: |
| 964 | rtm->rtm_addrs |= RTA_DST; |
| 965 | } |
| 966 | |
| 967 | NEXTADDR(RTA_DST, sin_m); |
| 968 | NEXTADDR(RTA_GATEWAY, sdl_m); |
| 969 | |
| 970 | rtm->rtm_msglen = cp - (char *)&m_rtmsg; |
| 971 | doit: |
| 972 | l = rtm->rtm_msglen; |
| 973 | rtm->rtm_seq = ++seq; |
| 974 | rtm->rtm_type = cmd; |
| 975 | #ifndef FSTACK |
| 976 | if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { |
| 977 | if (errno != ESRCH || cmd != RTM_DELETE) { |
| 978 | err(1, "writing to routing socket"); |
| 979 | /* NOTREACHED */ |
| 980 | } |
| 981 | } |
| 982 | do { |
| 983 | l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); |
| 984 | } while (l > 0 && (rtm->rtm_type != cmd || rtm->rtm_seq != seq || |
| 985 | rtm->rtm_pid != pid)); |
| 986 | #else |
| 987 | l = rtioctl((char *)&m_rtmsg, l, sizeof(m_rtmsg)); |
| 988 | #endif |
| 989 | if (l < 0) |
| 990 | (void) fprintf(stderr, "ndp: read from routing socket: %s\n", |
| 991 | strerror(errno)); |
| 992 | return (0); |