diff options
author | Harald Welte <laforge@gnumonks.org> | 2010-05-19 15:53:22 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-05-19 15:53:22 +0200 |
commit | 6c4136e347b2053bd2fe849dc2ca7c2e7e4ada45 (patch) | |
tree | 423a75064b726d9ab8075b2f8947fd9b7441f964 /openbsc/src | |
parent | b11226d77aa17bcc00177a7fcfddf9569db544fc (diff) |
[GPRS] NS: SOCK_RAW sockets always provide the full IPv4 header on receive
Diffstat (limited to 'openbsc/src')
-rw-r--r-- | openbsc/src/gprs/gprs_ns_frgre.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/openbsc/src/gprs/gprs_ns_frgre.c b/openbsc/src/gprs/gprs_ns_frgre.c index 359c0f71..baa7e521 100644 --- a/openbsc/src/gprs/gprs_ns_frgre.c +++ b/openbsc/src/gprs/gprs_ns_frgre.c @@ -29,6 +29,7 @@ #include <sys/socket.h> #include <netinet/in.h> +#include <netinet/ip.h> #include <arpa/inet.h> #include <osmocore/select.h> @@ -52,6 +53,7 @@ static struct msgb *read_nsfrgre_msg(struct bsc_fd *bfd, int *error, struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "Gb/NS/FR/GRE Rx"); int ret = 0; socklen_t saddr_len = sizeof(*saddr); + struct iphdr *iph; struct gre_hdr *greh; uint8_t *frh; uint32_t dlci; @@ -75,13 +77,20 @@ static struct msgb *read_nsfrgre_msg(struct bsc_fd *bfd, int *error, msgb_put(msg, ret); - if (msg->len < sizeof(*greh)) { - LOGP(DNS, LOGL_ERROR, "Short GRE packet: %u bytes\n", msg->len); + if (msg->len < sizeof(*iph) + sizeof(*greh) + 2) { + LOGP(DNS, LOGL_ERROR, "Short IP packet: %u bytes\n", msg->len); *error = -EIO; goto out_err; } - greh = (struct gre_hdr *) msg->data; + iph = (struct iphdr *) msg->data; + if (msg->len < (iph->ihl*4 + sizeof(*greh) + 2)) { + LOGP(DNS, LOGL_ERROR, "Short IP packet: %u bytes\n", msg->len); + *error = -EIO; + goto out_err; + } + + greh = (struct gre_hdr *) (msg->data + iph->ihl*4); if (greh->flags) { LOGP(DNS, LOGL_NOTICE, "Unknown GRE flags 0x%04x\n", ntohs(greh->flags)); @@ -99,7 +108,7 @@ static struct msgb *read_nsfrgre_msg(struct bsc_fd *bfd, int *error, goto out_err; } - frh = msg->data + sizeof(*greh); + frh = (uint8_t *)greh + sizeof(*greh); if (frh[0] & 0x01) { LOGP(DNS, LOGL_NOTICE, "Unsupported single-byte FR address\n"); *error = -EIO; @@ -120,7 +129,7 @@ static struct msgb *read_nsfrgre_msg(struct bsc_fd *bfd, int *error, goto out_err; } - msg->l2h = msg->data + sizeof(*greh) + 2; + msg->l2h = frh+2; /* Store DLCI in NETWORK BYTEORDER in sockaddr port member */ saddr->sin_port = htons(dlci & 0xffff); |