1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45:
46:
47: 48: 49: 50:
51:
52: #include <tk/tkernel.h>
53:
54: #include <t2ex/socket.h>
55:
56: #include <stdio.h>
57: #include <strings.h>
58:
59: #include "util.h"
60:
61: static void route_cmd(int cmd, in_addr_t dest, in_addr_t gate, in_addr_t mask, int index, int direct)
62: {
63: int i = 0;
64: int sock;
65: int re;
66: struct {
67: struct rt_msghdr rtm;
68: struct sockaddr_in addr[3];
69: } buf;
70:
71: bzero(&buf, sizeof buf);
72: buf.rtm.rtm_version = RTM_VERSION;
73: buf.rtm.rtm_type = cmd;
74: buf.rtm.rtm_index = index;
75: buf.rtm.rtm_flags = RTF_STATIC;
76: if ( direct ) {
77: buf.rtm.rtm_flags |= RTF_HOST;
78: } else {
79: buf.rtm.rtm_flags |= RTF_GATEWAY;
80: }
81: buf.rtm.rtm_addrs = RTA_DST | RTA_NETMASK;
82: if ( gate != 0 ) {
83: buf.rtm.rtm_addrs |= RTA_GATEWAY;
84: }
85: buf.rtm.rtm_inits = RTV_HOPCOUNT;
86: buf.rtm.rtm_rmx.rmx_hopcount = 1;
87: buf.rtm.rtm_seq = 1;
88:
89: buf.addr[i].sin_len = sizeof(struct sockaddr_in);
90: buf.addr[i].sin_family = AF_INET;
91: buf.addr[i].sin_addr.s_addr = dest;
92: i++;
93:
94: if ( gate != 0 ) {
95: buf.addr[i].sin_len = sizeof(struct sockaddr_in);
96: buf.addr[i].sin_family = AF_INET;
97: buf.addr[i].sin_addr.s_addr = gate;
98: i++;
99: }
100:
101: buf.addr[i].sin_len = sizeof(struct sockaddr_in);
102: buf.addr[i].sin_family = AF_INET;
103: buf.addr[i].sin_addr.s_addr = mask;
104: i++;
105:
106: buf.rtm.rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr) * i;
107:
108: sock = so_socket(AF_ROUTE, SOCK_RAW, 0);
109: DEBUG_PRINT(("route_add: so_socket = %d(%d, %d)\n", sock, MERCD(sock), SERCD(sock)));
110: so_shutdown(sock, SHUT_RD);
111: re = so_write(sock, &buf, buf.rtm.rtm_msglen);
112: DEBUG_PRINT(("route_add: so_write = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
113: so_close(sock);
114: }
115:
116: void route_change(in_addr_t dest, in_addr_t gate, in_addr_t mask, int index, int direct)
117: {
118: route_cmd(RTM_CHANGE, dest, gate, mask, index, direct);
119: }
120:
121: void route_delete(in_addr_t dest, in_addr_t mask, int index, int direct)
122: {
123: route_cmd(RTM_DELETE, dest, 0, mask, index, direct);
124: }
125:
126: void route_add(in_addr_t dest, in_addr_t gate, in_addr_t mask, int index, int direct)
127: {
128: route_cmd(RTM_ADD, dest, gate, mask, index, direct);
129: }
130:
131: #define ROUNDUP(a) \
132: ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
133:
134: static void get_rtaddrs(int addrs, struct sockaddr* sa, struct sockaddr** rti_info)
135: {
136: int i;
137:
138: for (i = 0; i < RTAX_MAX; i++) {
139: if ( addrs & (1 << i) ) {
140: rti_info[i] = sa;
141: sa = (struct sockaddr*)((char*)sa + ROUNDUP(sa->sa_len));
142: } else {
143: rti_info[i] = NULL;
144: }
145: }
146: }
147:
148: static void np_rtentry(struct rt_msghdr* rtm)
149: {
150: char ifname[IFNAMSIZ + 1];
151: struct sockaddr *rti_info[RTAX_MAX];
152: struct sockaddr_in* dest = NULL;
153: struct sockaddr_in* mask = NULL;
154: struct sockaddr* sa;
155: char flags[33];
156: char* bp = flags;
157: char rbuf[18];
158: char workbuf[20];
159: int len;
160:
161: sa = (struct sockaddr*)(rtm + 1);
162: if (sa->sa_family != AF_INET)
163: return;
164:
165: if (rtm->rtm_flags & RTF_UP)
166: *bp++ = 'U';
167: if (rtm->rtm_flags & RTF_GATEWAY)
168: *bp++ = 'G';
169: if (rtm->rtm_flags & RTF_HOST)
170: *bp++ = 'H';
171: if (rtm->rtm_flags & RTF_STATIC)
172: *bp++ = 'S';
173: if (bp == flags)
174: return;
175: *bp = '\0';
176:
177: get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
178:
179: if ((rtm->rtm_addrs & RTA_DST) &&
180: rti_info[RTAX_DST]->sa_family == AF_INET) {
181: dest = (struct sockaddr_in*)rti_info[RTAX_DST];
182: }
183:
184: if ((rtm->rtm_addrs & RTA_NETMASK) &&
185: rti_info[RTAX_NETMASK]->sa_len != 0) {
186: mask = (struct sockaddr_in*)rti_info[RTAX_NETMASK];
187: }
188:
189: memset(workbuf, 0, sizeof(workbuf));
190: if (rtm->rtm_addrs & RTA_GATEWAY) {
191: len = so_getnameinfo(rti_info[RTAX_GATEWAY], rti_info[RTAX_GATEWAY]->sa_len,
192: workbuf, sizeof(workbuf), NULL, 0, NI_NUMERICHOST, NULL);
193: if (len < 0) {
194: strcpy(workbuf, "invalid");
195: }
196: }
197:
198: so_ifindextoname(rtm->rtm_index, ifname);
199:
200: printf("%-16s ", dest != NULL ? inet_ntop(AF_INET, &dest->sin_addr, rbuf, sizeof(rbuf)) : "-");
201: printf("%-16s ", mask != NULL ? inet_ntop(AF_INET, &mask->sin_addr, rbuf, sizeof(rbuf)) : "-");
202: printf("%-18s ", workbuf[0] != '\0' ? workbuf : "-");
203: printf(" %-8s ", flags);
204: printf(" %-6s ", ifname);
205: printf(" %d ", rtm->rtm_index);
206:
207: printf("\n");
208: }
209:
210: void dump_rtlist(void)
211: {
212: union {
213: struct rt_msghdr rt;
214: char buf[4096];
215: } rtbuf;
216: struct rt_msghdr* rtm;
217: ER er;
218:
219: printf("Destination Netmask Gateway Flags Interface\n");
220: er = so_rtlist(AF_INET, NET_RT_DUMP, 0, &rtbuf, sizeof(rtbuf) );
221: DEBUG_PRINT(("dump_rtlist: so_rtlist = %d(%d, %d)\n", er, MERCD(er), SERCD(er)));
222: for(rtm = &rtbuf.rt; rtm->rtm_msglen != 0; rtm = (struct rt_msghdr *)((void*)rtm + rtm->rtm_msglen) ) {
223: np_rtentry(rtm);
224: }
225: }
226: