aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-05-19 15:53:22 +0200
committerHarald Welte <laforge@gnumonks.org>2010-05-19 15:53:22 +0200
commitea92ac377781fc7f6a3c923f66051b4e63b2153f (patch)
tree3896e3768ab879f50ce6fa3d161302498c415c0b
parentffe191c4775293d3d785cec49377db5ece7a59a3 (diff)
[GPRS] NS: SOCK_RAW sockets always provide the full IPv4 header on receive
-rw-r--r--openbsc/src/gprs/gprs_ns_frgre.c19
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 359c0f711..baa7e5217 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);