- Turn off ssl support by default
[openvswitch] / switch / netdev.c
1 /* Copyright (C) 2008 Board of Trustees, Leland Stanford Jr. University.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21
22 #include "netdev.h"
23
24 #include <assert.h>
25 #include <errno.h>
26 #include <arpa/inet.h>
27 #include <inttypes.h>
28 #include <linux/types.h>
29 #include <linux/ethtool.h>
30 #include <linux/sockios.h>
31 #include <sys/types.h>
32 #include <sys/ioctl.h>
33 #include <sys/socket.h>
34 #include <netpacket/packet.h>
35 #include <net/ethernet.h>
36 #include <net/if.h>
37 #include <net/if_arp.h>
38 #include <net/if_packet.h>
39 #include <netinet/in.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43
44 #include "list.h"
45 #include "fatal-signal.h"
46 #include "buffer.h"
47 #include "openflow.h"
48 #include "packets.h"
49
50 #define THIS_MODULE VLM_netdev
51 #include "vlog.h"
52
53 struct netdev {
54     struct list node;
55     char *name;
56     int fd;
57     uint8_t etheraddr[ETH_ADDR_LEN];
58     int speed;
59     uint32_t features;
60     int save_flags;
61 };
62
63 static struct list netdev_list = LIST_INITIALIZER(&netdev_list);
64
65 static void init_netdev(void);
66 static int restore_flags(struct netdev *netdev);
67
68 /* Check whether device NAME has an IPv4 address assigned to it and, if so, log
69  * an error. */
70 static void
71 check_ipv4_address(const char *name)
72 {
73     int sock;
74     struct ifreq ifr;
75
76     sock = socket(AF_INET, SOCK_DGRAM, 0);
77     if (sock < 0) {
78         VLOG_WARN("socket(AF_INET): %s", strerror(errno));
79         return;
80     }
81
82     strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
83     ifr.ifr_addr.sa_family = AF_INET;
84     if (ioctl(sock, SIOCGIFADDR, &ifr) == 0) {
85         VLOG_ERR("%s device has assigned IP address %s", name,
86                  inet_ntoa(((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr));
87     }
88
89     close(sock);
90 }
91
92 static void
93 check_ipv6_address(const char *name)
94 {
95     FILE *file;
96     char line[128];
97
98     file = fopen("/proc/net/if_inet6", "r");
99     if (file == NULL) {
100         return;
101     }
102
103     while (fgets(line, sizeof line, file)) {
104         struct in6_addr in6;
105         uint8_t *s6 = in6.s6_addr;
106         char ifname[16 + 1];
107
108 #define X8 "%2"SCNx8
109         if (sscanf(line, " "X8 X8 X8 X8 X8 X8 X8 X8 X8 X8 X8 X8 X8 X8 X8 X8
110                    "%*x %*x %*x %*x %16s\n",
111                    &s6[0], &s6[1], &s6[2], &s6[3],
112                    &s6[4], &s6[5], &s6[6], &s6[7],
113                    &s6[8], &s6[9], &s6[10], &s6[11],
114                    &s6[12], &s6[13], &s6[14], &s6[15],
115                    ifname) == 17
116             && !strcmp(name, ifname))
117         {
118             char in6_name[INET6_ADDRSTRLEN + 1];
119             inet_ntop(AF_INET6, &in6, in6_name, sizeof in6_name);
120             VLOG_ERR("%s device has assigned IPv6 address %s",
121                      name, in6_name);
122         }
123     }
124
125     fclose(file);
126 }
127
128 static void
129 do_ethtool(struct netdev *netdev) 
130 {
131     struct ifreq ifr;
132     struct ethtool_cmd ecmd;
133
134     netdev->speed = 0;
135     netdev->features = 0;
136
137     memset(&ifr, 0, sizeof ifr);
138     strncpy(ifr.ifr_name, netdev->name, sizeof ifr.ifr_name);
139     ifr.ifr_data = (caddr_t) &ecmd;
140
141     memset(&ecmd, 0, sizeof ecmd);
142     ecmd.cmd = ETHTOOL_GSET;
143     if (ioctl(netdev->fd, SIOCETHTOOL, &ifr) == 0) {
144         if (ecmd.supported & SUPPORTED_10baseT_Half) {
145             netdev->features |= OFPPF_10MB_HD;
146         }
147         if (ecmd.supported & SUPPORTED_10baseT_Full) {
148             netdev->features |= OFPPF_10MB_FD;
149         }
150         if (ecmd.supported & SUPPORTED_100baseT_Half)  {
151             netdev->features |= OFPPF_100MB_HD;
152         }
153         if (ecmd.supported & SUPPORTED_100baseT_Full) {
154             netdev->features |= OFPPF_100MB_FD;
155         }
156         if (ecmd.supported & SUPPORTED_1000baseT_Half) {
157             netdev->features |= OFPPF_1GB_HD;
158         }
159         if (ecmd.supported & SUPPORTED_1000baseT_Full) {
160             netdev->features |= OFPPF_1GB_FD;
161         }
162         /* 10Gbps half-duplex doesn't exist... */
163         if (ecmd.supported & SUPPORTED_10000baseT_Full) {
164             netdev->features |= OFPPF_10GB_FD;
165         }
166
167         switch (ecmd.speed) {
168         case SPEED_10:
169             netdev->speed = 10;
170             break;
171
172         case SPEED_100:
173             netdev->speed = 100;
174             break;
175
176         case SPEED_1000:
177             netdev->speed = 1000;
178             break;
179
180         case SPEED_2500:
181             netdev->speed = 2500;
182             break;
183
184         case SPEED_10000:
185             netdev->speed = 10000;
186             break;
187         }
188     } else {
189         VLOG_DBG("ioctl(SIOCETHTOOL) failed: %s", strerror(errno));
190     }
191 }
192
193 int
194 netdev_open(const char *name, struct netdev **netdev_)
195 {
196     int fd;
197     struct sockaddr sa;
198     struct ifreq ifr;
199     unsigned int ifindex;
200     socklen_t rcvbuf_len;
201     size_t rcvbuf;
202     uint8_t etheraddr[ETH_ADDR_LEN];
203     int error;
204     struct netdev *netdev;
205
206     *netdev_ = NULL;
207     init_netdev();
208
209     /* Create raw socket.
210      *
211      * We have to use SOCK_PACKET, despite its deprecation, because only
212      * SOCK_PACKET lets us set the hardware source address of outgoing
213      * packets. */
214     fd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ALL));
215     if (fd < 0) {
216         return errno;
217     }
218
219     /* Bind to specific ethernet device. */
220     memset(&sa, 0, sizeof sa);
221     sa.sa_family = AF_UNSPEC;
222     strncpy((char *) sa.sa_data, name, sizeof sa.sa_data);
223     if (bind(fd, &sa, sizeof sa) < 0) {
224         VLOG_ERR("bind to %s failed: %s", name, strerror(errno));
225         goto error;
226     }
227
228     /* Between the socket() and bind() calls above, the socket receives all
229      * packets on all system interfaces.  We do not want to receive that
230      * data, but there is no way to avoid it.  So we must now drain out the
231      * receive queue.  There is no way to know how long the receive queue is,
232      * but we know that the total number of byted queued does not exceed the
233      * receive buffer size, so we pull packets until none are left or we've
234      * read that many bytes. */
235     rcvbuf_len = sizeof rcvbuf;
236     if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &rcvbuf_len) < 0) {
237         VLOG_ERR("getsockopt(SO_RCVBUF) on %s device failed: %s",
238                  name, strerror(errno));
239         goto error;
240     }
241     while (rcvbuf > 0) {
242         char buffer;
243         ssize_t n_bytes = recv(fd, &buffer, 1, MSG_TRUNC | MSG_DONTWAIT);
244         if (n_bytes <= 0) {
245             break;
246         }
247         rcvbuf -= n_bytes;
248     }
249
250     /* Get ethernet device index and hardware address. */
251     strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
252     if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
253         VLOG_ERR("ioctl(SIOCGIFINDEX) on %s device failed: %s",
254                  name, strerror(errno));
255         goto error;
256     }
257     ifindex = ifr.ifr_ifindex;
258     if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
259         VLOG_ERR("ioctl(SIOCGIFHWADDR) on %s device failed: %s",
260                  name, strerror(errno));
261         goto error;
262     }
263     if (ifr.ifr_hwaddr.sa_family != AF_UNSPEC
264         && ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
265         VLOG_WARN("%s device has unknown hardware address family %d",
266                   name, (int) ifr.ifr_hwaddr.sa_family);
267     }
268     memcpy(etheraddr, ifr.ifr_hwaddr.sa_data, sizeof etheraddr);
269
270     /* Allocate network device. */
271     netdev = xmalloc(sizeof *netdev);
272     netdev->name = xstrdup(name);
273     netdev->fd = fd;
274     memcpy(netdev->etheraddr, etheraddr, sizeof etheraddr);
275
276     /* Get speed, features. */
277     do_ethtool(netdev);
278
279     /* Save flags to restore at close or exit. */
280     if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
281         VLOG_ERR("ioctl(SIOCGIFFLAGS) on %s device failed: %s",
282                  name, strerror(errno));
283         goto error;
284     }
285     netdev->save_flags = ifr.ifr_flags;
286     fatal_signal_block();
287     list_push_back(&netdev_list, &netdev->node);
288     fatal_signal_unblock();
289
290     /* Bring up interface and set promiscuous mode. */
291     ifr.ifr_flags |= IFF_PROMISC | IFF_UP;
292     if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
293         error = errno;
294         VLOG_ERR("failed to set promiscuous mode on %s device: %s",
295                  name, strerror(errno));
296         netdev_close(netdev);
297         return error;
298     }
299
300     /* Report IP addresses to administrator. */
301     check_ipv4_address(name);
302     check_ipv6_address(name);
303
304     /* Success! */
305     *netdev_ = netdev;
306     return 0;
307
308 error:
309     error = errno;
310     close(fd);
311     return error;
312 }
313
314 void
315 netdev_close(struct netdev *netdev)
316 {
317     if (netdev) {
318         /* Bring down interface and drop promiscuous mode, if we brought up
319          * the interface or enabled promiscuous mode. */
320         int error;
321         fatal_signal_block();
322         error = restore_flags(netdev);
323         list_remove(&netdev->node);
324         fatal_signal_unblock();
325         if (error) {
326             VLOG_WARN("failed to restore network device flags on %s: %s",
327                       netdev->name, strerror(error));
328         }
329
330         /* Free. */
331         free(netdev->name);
332         close(netdev->fd);
333         free(netdev);
334     }
335 }
336
337 static void
338 pad_to_minimum_length(struct buffer *buffer)
339 {
340     if (buffer->size < ETH_TOTAL_MIN) {
341         size_t shortage = ETH_TOTAL_MIN - buffer->size;
342         memset(buffer_put_uninit(buffer, shortage), 0, shortage);
343     }
344 }
345
346 int
347 netdev_recv(struct netdev *netdev, struct buffer *buffer, bool block)
348 {
349     ssize_t n_bytes;
350
351     assert(buffer->size == 0);
352     assert(buffer_tailroom(buffer) >= ETH_TOTAL_MIN);
353     do {
354         n_bytes = recv(netdev->fd,
355                        buffer_tail(buffer), buffer_tailroom(buffer),
356                        block ? 0 : MSG_DONTWAIT);
357     } while (n_bytes < 0 && errno == EINTR);
358     if (n_bytes < 0) {
359         if (errno != EAGAIN) {
360             VLOG_WARN("error receiving Ethernet packet on %s: %s",
361                       strerror(errno), netdev->name);
362         }
363         return errno;
364     } else {
365         buffer->size += n_bytes;
366
367         /* When the kernel internally sends out an Ethernet frame on an
368          * interface, it gives us a copy *before* padding the frame to the
369          * minimum length.  Thus, when it sends out something like an ARP
370          * request, we see a too-short frame.  So pad it out to the minimum
371          * length. */
372         pad_to_minimum_length(buffer);
373         return 0;
374     }
375 }
376
377 int
378 netdev_send(struct netdev *netdev, struct buffer *buffer, bool block)
379 {
380     ssize_t n_bytes;
381     const struct eth_header *eh;
382     struct sockaddr_pkt spkt;
383
384     /* Ensure packet is long enough.  (Although all incoming packets are at
385      * least ETH_TOTAL_MIN bytes long, we could have trimmed some data off a
386      * minimum-size packet, e.g. by dropping a vlan header.) */
387     pad_to_minimum_length(buffer);
388
389     /* Construct packet sockaddr, which SOCK_PACKET requires. */
390     spkt.spkt_family = AF_PACKET;
391     strncpy((char *) spkt.spkt_device, netdev->name, sizeof spkt.spkt_device);
392     eh = buffer_at_assert(buffer, 0, sizeof *eh);
393     spkt.spkt_protocol = eh->eth_type;
394
395     do {
396         n_bytes = sendto(netdev->fd, buffer->data, buffer->size,
397                          block ? 0 : MSG_DONTWAIT,
398                          (const struct sockaddr *) &spkt, sizeof spkt);
399     } while (n_bytes < 0 && errno == EINTR);
400     if (n_bytes < 0) {
401         if (errno != EAGAIN) {
402             VLOG_WARN("error sending Ethernet packet on %s: %s",
403                       netdev->name, strerror(errno)); 
404         }
405         return errno;
406     } else if (n_bytes != buffer->size) {
407         VLOG_WARN("send partial Ethernet packet (%d bytes of %d) on %s",
408                   (int) n_bytes, buffer->size, netdev->name);
409         return EMSGSIZE;
410     } else {
411         return 0;
412     }
413 }
414
415 const uint8_t *
416 netdev_get_etheraddr(const struct netdev *netdev)
417 {
418     return netdev->etheraddr;
419 }
420
421 int
422 netdev_get_fd(const struct netdev *netdev)
423 {
424     return netdev->fd;
425 }
426
427 const char *
428 netdev_get_name(const struct netdev *netdev)
429 {
430     return netdev->name;
431 }
432
433 int
434 netdev_get_speed(const struct netdev *netdev) 
435 {
436     return netdev->speed;
437 }
438
439 uint32_t
440 netdev_get_features(const struct netdev *netdev) 
441 {
442     return netdev->features;
443 }
444 \f
445 static void restore_all_flags(void *aux);
446
447 static void
448 init_netdev(void)
449 {
450     static bool inited;
451     if (!inited) {
452         inited = true;
453         fatal_signal_add_hook(restore_all_flags, NULL);
454     }
455 }
456
457 static int
458 restore_flags(struct netdev *netdev)
459 {
460     struct ifreq ifr;
461
462     /* Get current flags. */
463     strncpy(ifr.ifr_name, netdev->name, sizeof ifr.ifr_name);
464     if (ioctl(netdev->fd, SIOCGIFFLAGS, &ifr) < 0) {
465         return errno;
466     }
467
468     /* Restore flags that we might have changed, if necessary. */
469     if ((ifr.ifr_flags ^ netdev->save_flags) & (IFF_PROMISC | IFF_UP)) {
470         ifr.ifr_flags &= ~(IFF_PROMISC | IFF_UP);
471         ifr.ifr_flags |= netdev->save_flags & (IFF_PROMISC | IFF_UP);
472         if (ioctl(netdev->fd, SIOCSIFFLAGS, &ifr) < 0) {
473             return errno;
474         }
475     }
476
477     return 0;
478 }
479
480 static void
481 restore_all_flags(void *aux UNUSED)
482 {
483     struct netdev *netdev;
484     LIST_FOR_EACH (netdev, struct netdev, node, &netdev_list) {
485         restore_flags(netdev);
486     }
487 }