|
1 /* |
|
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
|
3 */ |
|
4 |
|
5 /* |
|
6 * Copyright (c) 2012 Ed Maste. All rights reserved. |
|
7 * |
|
8 * Licensed under the Apache License, Version 2.0 (the "License"); |
|
9 * you may not use this file except in compliance with the License. |
|
10 * You may obtain a copy of the License at: |
|
11 * |
|
12 * http://www.apache.org/licenses/LICENSE-2.0 |
|
13 * |
|
14 * Unless required by applicable law or agreed to in writing, software |
|
15 * distributed under the License is distributed on an "AS IS" BASIS, |
|
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
17 * See the License for the specific language governing permissions and |
|
18 * limitations under the License. |
|
19 */ |
|
20 |
|
21 #include <config.h> |
|
22 |
|
23 #include "route-table.h" |
|
24 #include <sys/socket.h> |
|
25 #include <sys/types.h> |
|
26 |
|
27 #include <net/if.h> |
|
28 #include <net/route.h> |
|
29 #include <net/if_dl.h> |
|
30 #include <netinet/in.h> |
|
31 |
|
32 #include <string.h> |
|
33 #include <unistd.h> |
|
34 |
|
35 #include "util.h" |
|
36 |
|
37 static int pid; |
|
38 static unsigned int register_count = 0; |
|
39 |
|
40 #define ROUNDUP_LONG(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof (long) - 1))) : \ |
|
41 sizeof (long)) |
|
42 #define RT_ADVANCE(x, n) ((x) += ROUNDUP_LONG(salen(n))) |
|
43 #define BUF_SIZE 2048 |
|
44 |
|
45 typedef struct rtmsg { |
|
46 struct rt_msghdr m_rtm; |
|
47 char m_space[BUF_SIZE]; |
|
48 } rtmsg_t; |
|
49 |
|
50 static int |
|
51 salen(const struct sockaddr *sa) |
|
52 { |
|
53 switch (sa->sa_family) { |
|
54 case AF_INET: |
|
55 return (sizeof (struct sockaddr_in)); |
|
56 case AF_LINK: |
|
57 return (sizeof (struct sockaddr_dl)); |
|
58 case AF_INET6: |
|
59 return (sizeof (struct sockaddr_in6)); |
|
60 default: |
|
61 return (sizeof (struct sockaddr)); |
|
62 } |
|
63 } |
|
64 |
|
65 bool |
|
66 route_table_get_name(ovs_be32 ip, char name[IFNAMSIZ]) |
|
67 { |
|
68 rtmsg_t m_rtmsg; |
|
69 struct rt_msghdr *rtm = &m_rtmsg.m_rtm; |
|
70 char *cp = m_rtmsg.m_space; |
|
71 int rtsock_fd; |
|
72 struct sockaddr_in sin; |
|
73 struct sockaddr_dl sdl; |
|
74 ssize_t ssz; |
|
75 static int seq; |
|
76 int rlen; |
|
77 int i; |
|
78 int l; |
|
79 |
|
80 rtsock_fd = socket(PF_ROUTE, SOCK_RAW, 0); |
|
81 if (rtsock_fd == -1) |
|
82 return (false); |
|
83 |
|
84 memset(&sin, 0, sizeof (sin)); |
|
85 sin.sin_family = AF_INET; |
|
86 sin.sin_port = 0; |
|
87 sin.sin_addr.s_addr = ip; |
|
88 |
|
89 memset(&sdl, 0, sizeof (sdl)); |
|
90 sdl.sdl_family = AF_LINK; |
|
91 |
|
92 memset(&m_rtmsg, 0, sizeof (m_rtmsg)); |
|
93 rtm->rtm_version = RTM_VERSION; |
|
94 rtm->rtm_type = RTM_GET; |
|
95 rtm->rtm_addrs = RTA_DST|RTA_IFP; |
|
96 rtm->rtm_seq = ++seq; |
|
97 |
|
98 l = ROUNDUP_LONG(sizeof (struct sockaddr_in)); |
|
99 (void) memcpy(cp, &sin, l); |
|
100 cp += l; |
|
101 |
|
102 l = ROUNDUP_LONG(sizeof (struct sockaddr_dl)); |
|
103 (void) memcpy(cp, &sdl, l); |
|
104 cp += l; |
|
105 |
|
106 rtm->rtm_msglen = l = cp - (char *)&m_rtmsg; |
|
107 if ((rlen = write(rtsock_fd, (char *)&m_rtmsg, l)) < l) { |
|
108 close(rtsock_fd); |
|
109 return (false); |
|
110 } |
|
111 |
|
112 do { |
|
113 ssz = read(rtsock_fd, &m_rtmsg, sizeof (m_rtmsg)); |
|
114 } while (ssz > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid)); |
|
115 close(rtsock_fd); |
|
116 |
|
117 if (ssz < 0) |
|
118 return (false); |
|
119 |
|
120 cp = (void *)&m_rtmsg.m_space; |
|
121 for (i = 1; i; i <<= 1) { |
|
122 if ((rtm->rtm_addrs & i) != 0) { |
|
123 const struct sockaddr *sa = (const void *)cp; |
|
124 |
|
125 if ((i == RTA_IFP) && sa->sa_family == AF_LINK) { |
|
126 const struct sockaddr_dl * const sdlp = |
|
127 ALIGNED_CAST(const struct sockaddr_dl *, |
|
128 sa); |
|
129 int namelen; |
|
130 |
|
131 namelen = sdlp->sdl_nlen; |
|
132 if (namelen > IFNAMSIZ - 1) |
|
133 namelen = IFNAMSIZ - 1; |
|
134 memcpy(name, sdlp->sdl_data, namelen); |
|
135 name[namelen] = '\0'; |
|
136 return (true); |
|
137 } |
|
138 RT_ADVANCE(cp, sa); |
|
139 } |
|
140 } |
|
141 return (false); |
|
142 } |
|
143 |
|
144 uint64_t |
|
145 route_table_get_change_seq(void) |
|
146 { |
|
147 return (0); |
|
148 } |
|
149 |
|
150 void |
|
151 route_table_register(void) |
|
152 { |
|
153 if (!register_count) { |
|
154 pid = getpid(); |
|
155 } |
|
156 |
|
157 register_count++; |
|
158 } |
|
159 |
|
160 void |
|
161 route_table_unregister(void) |
|
162 { |
|
163 register_count--; |
|
164 } |
|
165 |
|
166 void |
|
167 route_table_run(void) |
|
168 { |
|
169 } |
|
170 |
|
171 void |
|
172 route_table_wait(void) |
|
173 { |
|
174 } |