From: Ben Pfaff Date: Mon, 14 Jul 2008 20:03:09 +0000 (-0700) Subject: netdev: Do not modify the caller's buffer in netdev_send(). X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b563a5247c3535c1d9949351bdf4fc0194e79fbb;p=openvswitch netdev: Do not modify the caller's buffer in netdev_send(). This makes it possible to use a buffer whose contents are stack-allocated. --- diff --git a/include/netdev.h b/include/netdev.h index b90d34b7..06476e2e 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -57,7 +57,7 @@ int netdev_open(const char *name, struct netdev **); void netdev_close(struct netdev *); int netdev_recv(struct netdev *, struct buffer *); void netdev_recv_wait(struct netdev *); -int netdev_send(struct netdev *, struct buffer *); +int netdev_send(struct netdev *, const struct buffer *); const uint8_t *netdev_get_etheraddr(const struct netdev *); const char *netdev_get_name(const struct netdev *); int netdev_get_mtu(const struct netdev *); diff --git a/lib/netdev.c b/lib/netdev.c index 77508268..43592393 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -426,29 +426,30 @@ netdev_recv_wait(struct netdev *netdev) /* Sends 'buffer' on 'netdev'. Returns 0 if successful, otherwise a positive * errno value. Returns EAGAIN without blocking if the packet cannot be queued * immediately. Returns EMSGSIZE if a partial packet was transmitted or if - * the packet is too big to transmit on the device. + * the packet is too big or too small to transmit on the device. + * + * The caller retains ownership of 'buffer' in all cases. * * The kernel maintains a packet transmission queue, so the caller is not * expected to do additional queuing of packets. */ int -netdev_send(struct netdev *netdev, struct buffer *buffer) +netdev_send(struct netdev *netdev, const struct buffer *buffer) { ssize_t n_bytes; const struct eth_header *eh; struct sockaddr_pkt spkt; - /* Ensure packet is long enough. (Although all incoming packets are at - * least ETH_TOTAL_MIN bytes long, we could have trimmed some data off a - * minimum-size packet, e.g. by dropping a vlan header.) - * - * The kernel does not require this, but it ensures that we always access - * valid memory in grabbing the sockaddr below. */ - pad_to_minimum_length(buffer); + /* Pull out the Ethernet header. */ + if (buffer->size < ETH_HEADER_LEN) { + VLOG_WARN("cannot send %zu-byte frame on %s", + buffer->size, netdev->name); + return EMSGSIZE; + } + eh = buffer_at_assert(buffer, 0, sizeof *eh); /* Construct packet sockaddr, which SOCK_PACKET requires. */ spkt.spkt_family = AF_PACKET; strncpy((char *) spkt.spkt_device, netdev->name, sizeof spkt.spkt_device); - eh = buffer_at_assert(buffer, 0, sizeof *eh); spkt.spkt_protocol = eh->eth_type; do {