aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjjako <jjako>2004-02-05 20:39:57 +0000
committerjjako <jjako>2004-02-05 20:39:57 +0000
commit1f1586458fc940f487058b1bc0169eea1735eeb4 (patch)
tree51785635ece734b4b04f163d9f7d143b9bb2ed58
parent409b855839ea5035af48690c62f6340830267e13 (diff)
Added IP address alias capability for FreeBSD
-rw-r--r--ggsn/ggsn.c2
-rw-r--r--ggsn/tun.c45
-rw-r--r--gtp/gtp.c16
-rw-r--r--sgsnemu/tun.c45
4 files changed, 84 insertions, 24 deletions
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index b75b01d..c0592c9 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -90,7 +90,7 @@ void log_pid(char *pidfile) {
fclose(file);
}
-#ifdef __sun__
+#if defined(_sun__)
int daemon(int nochdir, int noclose) {
int fd;
diff --git a/ggsn/tun.c b/ggsn/tun.c
index 208cca6..b406fdb 100644
--- a/ggsn/tun.c
+++ b/ggsn/tun.c
@@ -343,22 +343,28 @@ int tun_addaddr(struct tun_t *this,
/* TODO: Is this needed on FreeBSD? */
if (!this->addrs) /* Use ioctl for first addr to make ping work */
- return tun_setaddr(this, addr, dstaddr, netmask);
+ return tun_setaddr(this, addr, dstaddr, netmask); /* TODO dstaddr */
memset(&areq, 0, sizeof(areq));
/* Set up interface name */
strncpy(areq.ifra_name, this->devname, IFNAMSIZ);
- ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
+ areq.ifra_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
- ((struct sockaddr_in) areq.ifra_addr).sin_family = AF_INET;
- ((struct sockaddr_in) areq.ifra_addr).sin_len = sizeof(areq.ifra_addr);
- ((struct sockaddr_in) areq.ifra_addr).sin_addr.s_addr = addr->s_addr;
+ ((struct sockaddr_in*) &areq.ifra_addr)->sin_family = AF_INET;
+ ((struct sockaddr_in*) &areq.ifra_addr)->sin_len = sizeof(areq.ifra_addr);
+ ((struct sockaddr_in*) &areq.ifra_addr)->sin_addr.s_addr = addr->s_addr;
- ((struct sockaddr_in) areq.ifra_mask).sin_family = AF_INET;
- ((struct sockaddr_in) areq.ifra_mask).sin_len = sizeof(areq.ifra_mask);
- ((struct sockaddr_in) areq.ifra_mask).sin_addr.s_addr = netmask->s_addr;
+ ((struct sockaddr_in*) &areq.ifra_mask)->sin_family = AF_INET;
+ ((struct sockaddr_in*) &areq.ifra_mask)->sin_len = sizeof(areq.ifra_mask);
+ ((struct sockaddr_in*) &areq.ifra_mask)->sin_addr.s_addr = netmask->s_addr;
+ /* For some reason FreeBSD uses ifra_broadcast for specifying dstaddr */
+ ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_family = AF_INET;
+ ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_len =
+ sizeof(areq.ifra_broadaddr);
+ ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_addr.s_addr =
+ dstaddr->s_addr;
/* Create a channel to the NET kernel. */
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
@@ -607,6 +613,8 @@ int tun_new(struct tun_t **tun)
#elif defined(__FreeBSD__)
char devname[IFNAMSIZ+5]; /* "/dev/" + ifname */
int devnum;
+ struct ifaliasreq areq;
+ int fd;
#elif defined(__sun__)
int if_fd, ppa = -1;
@@ -663,6 +671,27 @@ int tun_new(struct tun_t **tun)
snprintf((*tun)->devname, sizeof((*tun)->devname), "tun%d", devnum);
(*tun)->devname[sizeof((*tun)->devname)] = 0;
+
+ /* The tun device we found might have "old" IP addresses allocated */
+ /* We need to delete those. This problem is not present on Linux */
+
+ memset(&areq, 0, sizeof(areq));
+
+ /* Set up interface name */
+ strncpy(areq.ifra_name, (*tun)->devname, IFNAMSIZ);
+ areq.ifra_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
+
+ /* Create a channel to the NET kernel. */
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "socket() failed");
+ return -1;
+ }
+
+ /* Delete any IP addresses until SIOCDIFADDR fails */
+ while (ioctl(fd, SIOCDIFADDR, (void *) &areq) != -1);
+
+ close(fd);
return 0;
#elif defined(__sun__)
diff --git a/gtp/gtp.c b/gtp/gtp.c
index af4bdba..d4e5d74 100644
--- a/gtp/gtp.c
+++ b/gtp/gtp.c
@@ -407,7 +407,7 @@ int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr = *inetaddr;
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__)
addr.sin_len = sizeof(addr);
#endif
@@ -766,7 +766,7 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
addr.sin_family = AF_INET;
addr.sin_addr = *listen; /* Same IP for user traffic and signalling*/
addr.sin_port = htons(GTP0_PORT);
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__)
addr.sin_len = sizeof(addr);
#endif
@@ -787,7 +787,7 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
addr.sin_family = AF_INET;
addr.sin_addr = *listen; /* Same IP for user traffic and signalling*/
addr.sin_port = htons(GTP1C_PORT);
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__)
addr.sin_len = sizeof(addr);
#endif
@@ -808,7 +808,7 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
addr.sin_family = AF_INET;
addr.sin_addr = *listen; /* Same IP for user traffic and signalling*/
addr.sin_port = htons(GTP1U_PORT);
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__)
addr.sin_len = sizeof(addr);
#endif
@@ -2944,7 +2944,7 @@ int gtp_data_req(struct gsn_t *gsn, struct pdp_t* pdp,
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__)
addr.sin_len = sizeof(addr);
#endif
@@ -2965,7 +2965,8 @@ int gtp_data_req(struct gsn_t *gsn, struct pdp_t* pdp,
if (len > sizeof (union gtp_packet) - sizeof(struct gtp0_header)) {
gsn->err_memcpy++;
gtp_err(LOG_ERR, __FILE__, __LINE__,
- "Memcpy failed");
+ "Memcpy failed: %d > %d", len,
+ sizeof (union gtp_packet) - sizeof(struct gtp0_header));
return EOF;
}
memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
@@ -2985,7 +2986,8 @@ int gtp_data_req(struct gsn_t *gsn, struct pdp_t* pdp,
if (len > sizeof (union gtp_packet) - sizeof(struct gtp1_header_long)) {
gsn->err_memcpy++;
gtp_err(LOG_ERR, __FILE__, __LINE__,
- "Memcpy failed");
+ "Memcpy failed: %d > %d", len,
+ sizeof (union gtp_packet) - sizeof(struct gtp0_header));
return EOF;
}
memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
diff --git a/sgsnemu/tun.c b/sgsnemu/tun.c
index 208cca6..b406fdb 100644
--- a/sgsnemu/tun.c
+++ b/sgsnemu/tun.c
@@ -343,22 +343,28 @@ int tun_addaddr(struct tun_t *this,
/* TODO: Is this needed on FreeBSD? */
if (!this->addrs) /* Use ioctl for first addr to make ping work */
- return tun_setaddr(this, addr, dstaddr, netmask);
+ return tun_setaddr(this, addr, dstaddr, netmask); /* TODO dstaddr */
memset(&areq, 0, sizeof(areq));
/* Set up interface name */
strncpy(areq.ifra_name, this->devname, IFNAMSIZ);
- ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
+ areq.ifra_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
- ((struct sockaddr_in) areq.ifra_addr).sin_family = AF_INET;
- ((struct sockaddr_in) areq.ifra_addr).sin_len = sizeof(areq.ifra_addr);
- ((struct sockaddr_in) areq.ifra_addr).sin_addr.s_addr = addr->s_addr;
+ ((struct sockaddr_in*) &areq.ifra_addr)->sin_family = AF_INET;
+ ((struct sockaddr_in*) &areq.ifra_addr)->sin_len = sizeof(areq.ifra_addr);
+ ((struct sockaddr_in*) &areq.ifra_addr)->sin_addr.s_addr = addr->s_addr;
- ((struct sockaddr_in) areq.ifra_mask).sin_family = AF_INET;
- ((struct sockaddr_in) areq.ifra_mask).sin_len = sizeof(areq.ifra_mask);
- ((struct sockaddr_in) areq.ifra_mask).sin_addr.s_addr = netmask->s_addr;
+ ((struct sockaddr_in*) &areq.ifra_mask)->sin_family = AF_INET;
+ ((struct sockaddr_in*) &areq.ifra_mask)->sin_len = sizeof(areq.ifra_mask);
+ ((struct sockaddr_in*) &areq.ifra_mask)->sin_addr.s_addr = netmask->s_addr;
+ /* For some reason FreeBSD uses ifra_broadcast for specifying dstaddr */
+ ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_family = AF_INET;
+ ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_len =
+ sizeof(areq.ifra_broadaddr);
+ ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_addr.s_addr =
+ dstaddr->s_addr;
/* Create a channel to the NET kernel. */
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
@@ -607,6 +613,8 @@ int tun_new(struct tun_t **tun)
#elif defined(__FreeBSD__)
char devname[IFNAMSIZ+5]; /* "/dev/" + ifname */
int devnum;
+ struct ifaliasreq areq;
+ int fd;
#elif defined(__sun__)
int if_fd, ppa = -1;
@@ -663,6 +671,27 @@ int tun_new(struct tun_t **tun)
snprintf((*tun)->devname, sizeof((*tun)->devname), "tun%d", devnum);
(*tun)->devname[sizeof((*tun)->devname)] = 0;
+
+ /* The tun device we found might have "old" IP addresses allocated */
+ /* We need to delete those. This problem is not present on Linux */
+
+ memset(&areq, 0, sizeof(areq));
+
+ /* Set up interface name */
+ strncpy(areq.ifra_name, (*tun)->devname, IFNAMSIZ);
+ areq.ifra_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
+
+ /* Create a channel to the NET kernel. */
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "socket() failed");
+ return -1;
+ }
+
+ /* Delete any IP addresses until SIOCDIFADDR fails */
+ while (ioctl(fd, SIOCDIFADDR, (void *) &areq) != -1);
+
+ close(fd);
return 0;
#elif defined(__sun__)