patch-2.1.111 linux/net/ax25/af_ax25.c
Next file: linux/net/ax25/ax25_addr.c
Previous file: linux/mm/slab.c
Back to the patch index
Back to the overall index
- Lines: 345
- Date:
Wed Jul 22 13:45:58 1998
- Orig file:
v2.1.110/linux/net/ax25/af_ax25.c
- Orig date:
Sun Jun 7 11:16:40 1998
diff -u --recursive --new-file v2.1.110/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
@@ -1,5 +1,5 @@
/*
- * AX.25 release 037
+ * AX.25 release 038
*
* This code REQUIRES 2.1.15 or higher/ NET3.038
*
@@ -93,6 +93,8 @@
* Joerg(DL1BKE) Fixed DAMA Slave.
* Jonathan(G4KLX) Fix widlcard listen parameter setting.
* AX.25 037 Jonathan(G4KLX) New timer architecture.
+ * AX.25 038 Matthias(DG2FEF) Small fixes to the syscall interface to make kernel
+ * independent of AX25_MAX_DIGIS used by applications.
*/
#include <linux/config.h>
@@ -449,8 +451,10 @@
static int ax25_ctl_ioctl(const unsigned int cmd, void *arg)
{
struct ax25_ctl_struct ax25_ctl;
+ ax25_digi digi;
ax25_dev *ax25_dev;
ax25_cb *ax25;
+ unsigned int k;
if (copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl)))
return -EFAULT;
@@ -458,7 +462,11 @@
if ((ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr)) == NULL)
return -ENODEV;
- if ((ax25 = ax25_find_cb(&ax25_ctl.source_addr, &ax25_ctl.dest_addr, NULL, ax25_dev->dev)) == NULL)
+ digi.ndigi = ax25_ctl.digi_count;
+ for (k = 0; k < digi.ndigi; k++)
+ digi.calls[k] = ax25_ctl.digi_addr[k];
+
+ if ((ax25 = ax25_find_cb(&ax25_ctl.source_addr, &ax25_ctl.dest_addr, &digi, ax25_dev->dev)) == NULL)
return -ENOTCONN;
switch (ax25_ctl.cmd) {
@@ -1018,7 +1026,7 @@
SOCK_DEBUG(sk, "AX25: source address set to %s\n", ax2asc(&sk->protinfo.ax25->source_addr));
- if (addr_len == sizeof(struct full_sockaddr_ax25) && addr->fsa_ax25.sax25_ndigis == 1) {
+ if (addr_len > sizeof(struct sockaddr_ax25) && addr->fsa_ax25.sax25_ndigis == 1) {
if (ax25cmp(&addr->fsa_digipeater[0], &null_ax25_address) == 0) {
ax25_dev = NULL;
SOCK_DEBUG(sk, "AX25: bound to any device\n");
@@ -1057,14 +1065,20 @@
ax25_digi *digi = NULL;
int ct = 0, err;
- if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
- sock->state = SS_CONNECTED;
- return 0; /* Connect completed during a ERESTARTSYS event */
- }
+ /* deal with restarts */
+ if (sock->state == SS_CONNECTING) {
+ switch (sk->state) {
+ case TCP_SYN_SENT: /* still trying */
+ return -EINPROGRESS;
- if (sk->state == TCP_CLOSE && sock->state == SS_CONNECTING) {
- sock->state = SS_UNCONNECTED;
- return -ECONNREFUSED;
+ case TCP_ESTABLISHED: /* connection established */
+ sock->state = SS_CONNECTED;
+ return 0;
+
+ case TCP_CLOSE: /* connection refused */
+ sock->state = SS_UNCONNECTED;
+ return -ECONNREFUSED;
+ }
}
if (sk->state == TCP_ESTABLISHED && sk->type == SOCK_SEQPACKET)
@@ -1073,7 +1087,10 @@
sk->state = TCP_CLOSE;
sock->state = SS_UNCONNECTED;
- if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25))
+ /*
+ * some sanity checks. code further down depends on this
+ */
+ if (addr_len < sizeof(struct sockaddr_ax25) || addr_len > sizeof(struct full_sockaddr_ax25))
return -EINVAL;
if (fsa->fsa_ax25.sax25_family != AF_AX25)
@@ -1087,7 +1104,7 @@
/*
* Handle digi-peaters to be used.
*/
- if (addr_len == sizeof(struct full_sockaddr_ax25) && fsa->fsa_ax25.sax25_ndigis != 0) {
+ if (addr_len > sizeof(struct sockaddr_ax25) && fsa->fsa_ax25.sax25_ndigis != 0) {
/* Valid number of digipeaters ? */
if (fsa->fsa_ax25.sax25_ndigis < 1 || fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS)
return -EINVAL;
@@ -1202,10 +1219,17 @@
struct sock *newsk;
struct sk_buff *skb;
- if (newsock->sk != NULL)
- ax25_destroy_socket(newsock->sk->protinfo.ax25);
+ if (sock->state != SS_UNCONNECTED)
+ return -EINVAL;
- newsock->sk = NULL;
+ /*
+ * sys_accept has already allocated a struct sock. we need to free it,
+ * since we want to use the one provided by ax25_make_new.
+ */
+ if (newsock->sk != NULL) {
+ sk_free(newsock->sk);
+ newsock->sk = NULL;
+ }
if ((sk = sock->sk) == NULL)
return -EINVAL;
@@ -1245,43 +1269,43 @@
skb->sk = NULL;
kfree_skb(skb);
sk->ack_backlog--;
- newsock->sk = newsk;
+ newsock->sk = newsk;
+ newsock->state = SS_CONNECTED;
return 0;
}
static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
{
- struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr;
struct sock *sk = sock->sk;
unsigned char ndigi, i;
+ struct full_sockaddr_ax25 fsa;
if (peer != 0) {
if (sk->state != TCP_ESTABLISHED)
return -ENOTCONN;
- sax->fsa_ax25.sax25_family = AF_AX25;
- sax->fsa_ax25.sax25_call = sk->protinfo.ax25->dest_addr;
- sax->fsa_ax25.sax25_ndigis = 0;
- *uaddr_len = sizeof(struct full_sockaddr_ax25);
-
- if (sk->protinfo.ax25->digipeat != NULL) {
- ndigi = sk->protinfo.ax25->digipeat->ndigi;
- sax->fsa_ax25.sax25_ndigis = ndigi;
- for (i = 0; i < ndigi; i++)
- sax->fsa_digipeater[i] = sk->protinfo.ax25->digipeat->calls[i];
- }
+ fsa.fsa_ax25.sax25_family = AF_AX25;
+ fsa.fsa_ax25.sax25_call = sk->protinfo.ax25->dest_addr;
+ fsa.fsa_ax25.sax25_ndigis = 0;
+
+ ndigi = sk->protinfo.ax25->digipeat->ndigi;
+ fsa.fsa_ax25.sax25_ndigis = ndigi;
+ for (i = 0; i < ndigi; i++)
+ fsa.fsa_digipeater[i] = sk->protinfo.ax25->digipeat->calls[i];
} else {
- sax->fsa_ax25.sax25_family = AF_AX25;
- sax->fsa_ax25.sax25_call = sk->protinfo.ax25->source_addr;
- sax->fsa_ax25.sax25_ndigis = 1;
- *uaddr_len = sizeof(struct full_sockaddr_ax25);
-
- if (sk->protinfo.ax25->ax25_dev != NULL)
- memcpy(&sax->fsa_digipeater[0], sk->protinfo.ax25->ax25_dev->dev->dev_addr, AX25_ADDR_LEN);
- else
- sax->fsa_digipeater[0] = null_ax25_address;
+ fsa.fsa_ax25.sax25_family = AF_AX25;
+ fsa.fsa_ax25.sax25_call = sk->protinfo.ax25->source_addr;
+ fsa.fsa_ax25.sax25_ndigis = 1;
+ if (sk->protinfo.ax25->ax25_dev != NULL) {
+ memcpy(&fsa.fsa_digipeater[0], sk->protinfo.ax25->ax25_dev->dev->dev_addr, AX25_ADDR_LEN);
+ } else {
+ fsa.fsa_digipeater[0] = null_ax25_address;
+ }
}
+ if (*uaddr_len > sizeof (struct full_sockaddr_ax25))
+ *uaddr_len = sizeof (struct full_sockaddr_ax25);
+ memcpy(uaddr, &fsa, *uaddr_len);
return 0;
}
@@ -1315,11 +1339,14 @@
return -ENETUNREACH;
if (usax != NULL) {
- if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25))
- return -EINVAL;
if (usax->sax25_family != AF_AX25)
return -EINVAL;
- if (addr_len == sizeof(struct full_sockaddr_ax25) && usax->sax25_ndigis != 0) {
+ if (addr_len < sizeof(struct sockaddr_ax25) || addr_len > sizeof(struct full_sockaddr_ax25))
+ return -EINVAL;
+ if (addr_len < (usax->sax25_ndigis * AX25_ADDR_LEN + sizeof(struct sockaddr_ax25)))
+ return -EINVAL;
+
+ if (addr_len > sizeof(struct sockaddr_ax25) && usax->sax25_ndigis != 0) {
int ct = 0;
struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)usax;
@@ -1375,6 +1402,7 @@
/* User data follows immediately after the AX.25 data */
memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
+ skb->nh.raw = skb->data;
/* Add the PID if one is not supplied by the user in the skb */
if (!sk->protinfo.ax25->pidincl) {
@@ -1425,7 +1453,6 @@
static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm)
{
struct sock *sk = sock->sk;
- struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
int copied;
struct sk_buff *skb;
int er;
@@ -1453,13 +1480,13 @@
}
skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-
- if (sax != NULL) {
+
+ if (msg->msg_namelen != 0) {
+ struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
ax25_digi digi;
ax25_address dest;
- int dama;
- ax25_addr_parse(skb->data, skb->len, NULL, &dest, &digi, NULL, &dama);
+ ax25_addr_parse(skb->mac.raw+1, skb->data-skb->mac.raw-1, NULL, &dest, &digi, NULL, NULL);
sax->sax25_family = AF_AX25;
/* We set this correctly, even though we may not let the
@@ -1469,18 +1496,15 @@
sax->sax25_call = dest;
if (sax->sax25_ndigis != 0) {
- int ct = 0;
+ int ct;
struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)sax;
- while (ct < digi.ndigi) {
+ for (ct = 0; ct < digi.ndigi; ct++)
fsa->fsa_digipeater[ct] = digi.calls[ct];
- ct++;
- }
}
+ msg->msg_namelen = sizeof(struct full_sockaddr_ax25);
}
- msg->msg_namelen = sizeof(struct full_sockaddr_ax25);
-
skb_free_datagram(sk, skb);
return copied;
@@ -1614,56 +1638,53 @@
static int ax25_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
{
ax25_cb *ax25;
- const char *devname;
- char callbuf[15];
+ int k;
int len = 0;
off_t pos = 0;
off_t begin = 0;
cli();
- len += sprintf(buffer, "dest_addr src_addr dev st vs vr va t1 t2 t3 idle n2 rtt wnd paclen Snd-Q Rcv-Q inode\n");
-
+ /*
+ * New format:
+ * magic dev src_addr dest_addr,digi1,digi2,.. st vs vr va t1 t1 t2 t2 t3 t3 idle idle n2 n2 rtt window paclen Snd-Q Rcv-Q inode
+ */
+
for (ax25 = ax25_list; ax25 != NULL; ax25 = ax25->next) {
- if (ax25->ax25_dev == NULL)
- devname = "???";
- else
- devname = ax25->ax25_dev->dev->name;
-
- len += sprintf(buffer + len, "%-9s ",
- ax2asc(&ax25->dest_addr));
-
- sprintf(callbuf, "%s%c", ax2asc(&ax25->source_addr),
- (ax25->iamdigi) ? '*' : ' ');
-
- len += sprintf(buffer + len, "%-10s %-4s %2d %3d %3d %3d %3lu/%03lu %2lu/%02lu %3lu/%03lu %3lu/%03lu %2d/%02d %3lu %3d %5d",
- callbuf,
- devname,
+ len += sprintf(buffer+len, "%8.8lx %s %s%s ",
+ (long) ax25,
+ ax25->ax25_dev == NULL? "???" : ax25->ax25_dev->dev->name,
+ ax2asc(&ax25->source_addr),
+ ax25->iamdigi? "*":"");
+
+ len += sprintf(buffer+len, "%s", ax2asc(&ax25->dest_addr));
+
+ for (k=0; (ax25->digipeat != NULL) && (k < ax25->digipeat->ndigi); k++) {
+ len += sprintf(buffer+len, ",%s%s",
+ ax2asc(&ax25->digipeat->calls[k]),
+ ax25->digipeat->repeated[k]? "*":"");
+ }
+
+ len += sprintf(buffer+len, " %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %d %d",
ax25->state,
- ax25->vs,
- ax25->vr,
- ax25->va,
- ax25_display_timer(&ax25->t1timer) / HZ,
- ax25->t1 / HZ,
- ax25_display_timer(&ax25->t2timer) / HZ,
- ax25->t2 / HZ,
- ax25_display_timer(&ax25->t3timer) / HZ,
- ax25->t3 / HZ,
- ax25_display_timer(&ax25->idletimer) / (60 * HZ),
+ ax25->vs, ax25->vr, ax25->va,
+ ax25_display_timer(&ax25->t1timer) / HZ, ax25->t1 / HZ,
+ ax25_display_timer(&ax25->t2timer) / HZ, ax25->t2 / HZ,
+ ax25_display_timer(&ax25->t3timer) / HZ, ax25->t3 / HZ,
+ ax25_display_timer(&ax25->idletimer) / (60 * HZ),
ax25->idle / (60 * HZ),
- ax25->n2count,
- ax25->n2,
+ ax25->n2count, ax25->n2,
ax25->rtt / HZ,
ax25->window,
ax25->paclen);
if (ax25->sk != NULL) {
- len += sprintf(buffer + len, " %5d %5d %ld\n",
+ len += sprintf(buffer + len, " %d %d %ld\n",
atomic_read(&ax25->sk->wmem_alloc),
atomic_read(&ax25->sk->rmem_alloc),
ax25->sk->socket != NULL ? ax25->sk->socket->inode->i_ino : 0L);
} else {
- len += sprintf(buffer + len, "\n");
+ len += sprintf(buffer + len, " * * *\n");
}
pos = begin + len;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov