📄 af_ax25.c
字号:
sk->sleep = osk->sleep; sk->zapped = osk->zapped; ax25->modulus = osk->protinfo.ax25->modulus; ax25->backoff = osk->protinfo.ax25->backoff; ax25->pidincl = osk->protinfo.ax25->pidincl; ax25->iamdigi = osk->protinfo.ax25->iamdigi; ax25->rtt = osk->protinfo.ax25->rtt; ax25->t1 = osk->protinfo.ax25->t1; ax25->t2 = osk->protinfo.ax25->t2; ax25->t3 = osk->protinfo.ax25->t3; ax25->n2 = osk->protinfo.ax25->n2; ax25->idle = osk->protinfo.ax25->idle; ax25->paclen = osk->protinfo.ax25->paclen; ax25->window = osk->protinfo.ax25->window; ax25->ax25_dev = ax25_dev; ax25->source_addr = osk->protinfo.ax25->source_addr; if (osk->protinfo.ax25->digipeat != NULL) { if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { sk_free(sk); return NULL; } memcpy(ax25->digipeat, osk->protinfo.ax25->digipeat, sizeof(ax25_digi)); } sk->protinfo.ax25 = ax25; ax25->sk = sk; return sk;}static int ax25_release(struct socket *sock){ struct sock *sk = sock->sk; if (sk == NULL) return 0; if (sk->type == SOCK_SEQPACKET) { switch (sk->protinfo.ax25->state) { case AX25_STATE_0: ax25_disconnect(sk->protinfo.ax25, 0); ax25_destroy_socket(sk->protinfo.ax25); break; case AX25_STATE_1: case AX25_STATE_2: ax25_send_control(sk->protinfo.ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); ax25_disconnect(sk->protinfo.ax25, 0); ax25_destroy_socket(sk->protinfo.ax25); break; case AX25_STATE_3: case AX25_STATE_4: ax25_clear_queues(sk->protinfo.ax25); sk->protinfo.ax25->n2count = 0; switch (sk->protinfo.ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { case AX25_PROTO_STD_SIMPLEX: case AX25_PROTO_STD_DUPLEX: ax25_send_control(sk->protinfo.ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); ax25_stop_t2timer(sk->protinfo.ax25); ax25_stop_t3timer(sk->protinfo.ax25); ax25_stop_idletimer(sk->protinfo.ax25); break;#ifdef CONFIG_AX25_DAMA_SLAVE case AX25_PROTO_DAMA_SLAVE: ax25_stop_t3timer(sk->protinfo.ax25); ax25_stop_idletimer(sk->protinfo.ax25); break;#endif } ax25_calculate_t1(sk->protinfo.ax25); ax25_start_t1timer(sk->protinfo.ax25); sk->protinfo.ax25->state = AX25_STATE_2; sk->state = TCP_CLOSE; sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); sock_orphan(sk); sk->destroy = 1; break; default: break; } } else { sk->state = TCP_CLOSE; sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); sock_orphan(sk); ax25_destroy_socket(sk->protinfo.ax25); } sock->sk = NULL; sk->socket = NULL; /* Not used, but we should do this */ return 0;}/* * We support a funny extension here so you can (as root) give any callsign * digipeated via a local address as source. This hack is obsolete now * that we've implemented support for SO_BINDTODEVICE. It is however small * and trivially backward compatible. */static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len){ struct sock *sk = sock->sk; struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr; ax25_address *call; ax25_dev *ax25_dev = NULL; if (sk->zapped == 0) return -EINVAL; if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25)) { /* support for old structure may go away some time */ if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) || (addr_len > sizeof(struct full_sockaddr_ax25))) return -EINVAL; printk(KERN_WARNING "ax25_bind(): %s uses old (6 digipeater) socket structure.\n", current->comm); } if (addr->fsa_ax25.sax25_family != AF_AX25) return -EINVAL; call = ax25_findbyuid(current->euid); if (call == NULL && ax25_uid_policy && !capable(CAP_NET_ADMIN)) return -EACCES; if (call == NULL) sk->protinfo.ax25->source_addr = addr->fsa_ax25.sax25_call; else sk->protinfo.ax25->source_addr = *call; /* * User already set interface with SO_BINDTODEVICE */ if (sk->protinfo.ax25->ax25_dev != NULL) goto done; 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 = ax25_addr_ax25dev(&addr->fsa_digipeater[0])) == NULL) return -EADDRNOTAVAIL; } else { if ((ax25_dev = ax25_addr_ax25dev(&addr->fsa_ax25.sax25_call)) == NULL) return -EADDRNOTAVAIL; } if (ax25_dev != NULL) ax25_fillin_cb(sk->protinfo.ax25, ax25_dev);done: ax25_insert_socket(sk->protinfo.ax25); sk->zapped = 0; return 0;}/* * FIXME: nonblock behaviour looks like it may have a bug. */static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags){ struct sock *sk = sock->sk; struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr; ax25_digi *digi = NULL; int ct = 0, err; /* deal with restarts */ if (sock->state == SS_CONNECTING) { switch (sk->state) { case TCP_SYN_SENT: /* still trying */ return -EINPROGRESS; 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) return -EISCONN; /* No reconnect on a seqpacket socket */ sk->state = TCP_CLOSE; sock->state = SS_UNCONNECTED; /* * some sanity checks. code further down depends on this */ if (addr_len == sizeof(struct sockaddr_ax25)) { /* support for this will go away in early 2.5.x */ printk(KERN_WARNING "ax25_connect(): %s uses obsolete socket structure\n", current->comm); } else if (addr_len != sizeof(struct full_sockaddr_ax25)) { /* support for old structure may go away some time */ if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) || (addr_len > sizeof(struct full_sockaddr_ax25))) return -EINVAL; printk(KERN_WARNING "ax25_connect(): %s uses old (6 digipeater) socket structure.\n", current->comm); } if (fsa->fsa_ax25.sax25_family != AF_AX25) return -EINVAL; if (sk->protinfo.ax25->digipeat != NULL) { kfree(sk->protinfo.ax25->digipeat); sk->protinfo.ax25->digipeat = NULL; } /* * Handle digi-peaters to be used. */ 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; if ((digi = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL) return -ENOBUFS; digi->ndigi = fsa->fsa_ax25.sax25_ndigis; digi->lastrepeat = -1; while (ct < fsa->fsa_ax25.sax25_ndigis) { if ((fsa->fsa_digipeater[ct].ax25_call[6] & AX25_HBIT) && sk->protinfo.ax25->iamdigi) { digi->repeated[ct] = 1; digi->lastrepeat = ct; } else { digi->repeated[ct] = 0; } digi->calls[ct] = fsa->fsa_digipeater[ct]; ct++; } } /* * Must bind first - autobinding in this may or may not work. If * the socket is already bound, check to see if the device has * been filled in, error if it hasn't. */ if (sk->zapped) { /* check if we can remove this feature. It is broken. */ printk(KERN_WARNING "ax25_connect(): %s uses autobind, please contact jreuter@yaina.de\n", current->comm); if ((err = ax25_rt_autobind(sk->protinfo.ax25, &fsa->fsa_ax25.sax25_call)) < 0) return err; ax25_fillin_cb(sk->protinfo.ax25, sk->protinfo.ax25->ax25_dev); ax25_insert_socket(sk->protinfo.ax25); } else { if (sk->protinfo.ax25->ax25_dev == NULL) return -EHOSTUNREACH; } if (sk->type == SOCK_SEQPACKET && ax25_find_cb(&sk->protinfo.ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi, sk->protinfo.ax25->ax25_dev->dev) != NULL) { if (digi != NULL) kfree(digi); return -EADDRINUSE; /* Already such a connection */ } sk->protinfo.ax25->dest_addr = fsa->fsa_ax25.sax25_call; sk->protinfo.ax25->digipeat = digi; /* First the easy one */ if (sk->type != SOCK_SEQPACKET) { sock->state = SS_CONNECTED; sk->state = TCP_ESTABLISHED; return 0; } /* Move to connecting socket, ax.25 lapb WAIT_UA.. */ sock->state = SS_CONNECTING; sk->state = TCP_SYN_SENT; switch (sk->protinfo.ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { case AX25_PROTO_STD_SIMPLEX: case AX25_PROTO_STD_DUPLEX: ax25_std_establish_data_link(sk->protinfo.ax25); break;#ifdef CONFIG_AX25_DAMA_SLAVE case AX25_PROTO_DAMA_SLAVE: sk->protinfo.ax25->modulus = AX25_MODULUS; sk->protinfo.ax25->window = sk->protinfo.ax25->ax25_dev->values[AX25_VALUES_WINDOW]; if (sk->protinfo.ax25->ax25_dev->dama.slave) ax25_ds_establish_data_link(sk->protinfo.ax25); else ax25_std_establish_data_link(sk->protinfo.ax25); break;#endif } sk->protinfo.ax25->state = AX25_STATE_1; ax25_start_heartbeat(sk->protinfo.ax25); /* Now the loop */ if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) return -EINPROGRESS; cli(); /* To avoid races on the sleep */ /* A DM or timeout will go to closed, a UA will go to ABM */ while (sk->state == TCP_SYN_SENT) { interruptible_sleep_on(sk->sleep); if (signal_pending(current)) { sti(); return -ERESTARTSYS; } } if (sk->state != TCP_ESTABLISHED) { /* Not in ABM, not in WAIT_UA -> failed */ sti(); sock->state = SS_UNCONNECTED; return sock_error(sk); /* Always set at this point */ } sock->state = SS_CONNECTED; sti(); return 0;}static int ax25_accept(struct socket *sock, struct socket *newsock, int flags){ struct sock *sk; struct sock *newsk; struct sk_buff *skb; if (sock->state != SS_UNCONNECTED) return -EINVAL; if ((sk = sock->sk) == NULL) return -EINVAL; if (sk->type != SOCK_SEQPACKET) return -EOPNOTSUPP; if (sk->state != TCP_LISTEN) return -EINVAL; /* * The read queue this time is holding sockets ready to use * hooked into the SABM we saved */ do { if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) { if (flags & O_NONBLOCK) return -EWOULDBLOCK; interruptible_sleep_on(sk->sleep); if (signal_pending(current)) return -ERESTARTSYS; } } while (skb == NULL); newsk = skb->sk; newsk->pair = NULL; newsk->socket = newsock; newsk->sleep = &newsock->wait; /* Now attach up the new socket */ kfree_skb(skb); sk->ack_backlog--; 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 sock *sk = sock->sk; struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr; unsigned char ndigi, i; if (peer != 0) { if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; fsa->fsa_ax25.sax25_family = AF_AX25; fsa->fsa_ax25.sax25_call = sk->protinfo.ax25->dest_addr; fsa->fsa_ax25.sax25_ndigis = 0; if (sk->protinfo.ax25->digipeat != NULL) { 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 { 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; } } *uaddr_len = sizeof (struct full_sockaddr_ax25); return 0;}static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm){ struct sock *sk = sock->sk; struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name; int err; struct sockaddr_ax25 sax; struct sk_buff *skb; unsigned char *asmptr; int size; ax25_digi *dp; ax25_digi dtmp; int lv; int addr_len = msg->msg_namelen; if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR)) return -EINVAL; if (sk->zapped) return -EADDRNOTAVAIL; if (sk->shutdown & SEND_SHUTDOWN) { send_sig(SIGPIPE, current, 0); return -EPIPE; } if (sk->protinfo.ax25->ax25_dev == NULL) return -ENETUNREACH; if (usax != NULL) { if (usax->sax25_family != AF_AX25) return -EINVAL; if (addr_len == sizeof(struct sockaddr_ax25)) { printk(KERN_WARNING "ax25_sendmsg(): %s uses obsolete socket structure\n", current->comm); } else if (addr_len != sizeof(struct full_sockaddr_ax25)) { /* support for old structure may go away some time */ if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) || (addr_len > sizeof(struct full_sockaddr_ax25))) return -EINVAL; printk(KERN_WARNING "ax25_sendmsg(): %s uses old (6 digipeater) socket structure.\n", current->comm); } if (addr_len > sizeof(struct sockaddr_ax25) && usax->sax25_ndigis != 0) { int ct = 0; struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)usax; /* Valid number of digipeaters ? */ if (usax->sax25_ndigis < 1 || usax->sax25_ndigis > AX25_MAX_DIGIS)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -