📄 af_ax25.c
字号:
return -ENODEV; if (ax25_ctl.digi_count > AX25_MAX_DIGIS) return -EINVAL; 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) { case AX25_KILL: ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);#ifdef CONFIG_AX25_DAMA_SLAVE if (ax25_dev->dama.slave && ax25->ax25_dev->values[AX25_VALUES_PROTOCOL] == AX25_PROTO_DAMA_SLAVE) ax25_dama_off(ax25);#endif ax25_disconnect(ax25, ENETRESET); break; case AX25_WINDOW: if (ax25->modulus == AX25_MODULUS) { if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7) return -EINVAL; } else { if (ax25_ctl.arg < 1 || ax25_ctl.arg > 63) return -EINVAL; } ax25->window = ax25_ctl.arg; break; case AX25_T1: if (ax25_ctl.arg < 1) return -EINVAL; ax25->rtt = (ax25_ctl.arg * HZ) / 2; ax25->t1 = ax25_ctl.arg * HZ; break; case AX25_T2: if (ax25_ctl.arg < 1) return -EINVAL; ax25->t2 = ax25_ctl.arg * HZ; break; case AX25_N2: if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31) return -EINVAL; ax25->n2count = 0; ax25->n2 = ax25_ctl.arg; break; case AX25_T3: if (ax25_ctl.arg < 0) return -EINVAL; ax25->t3 = ax25_ctl.arg * HZ; break; case AX25_IDLE: if (ax25_ctl.arg < 0) return -EINVAL; ax25->idle = ax25_ctl.arg * 60 * HZ; break; case AX25_PACLEN: if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535) return -EINVAL; ax25->paclen = ax25_ctl.arg; break; default: return -EINVAL; } return 0;}/* * Fill in a created AX.25 created control block with the default * values for a particular device. */void ax25_fillin_cb(ax25_cb *ax25, ax25_dev *ax25_dev){ ax25->ax25_dev = ax25_dev; if (ax25->ax25_dev != NULL) { ax25->rtt = ax25_dev->values[AX25_VALUES_T1] / 2; ax25->t1 = ax25_dev->values[AX25_VALUES_T1]; ax25->t2 = ax25_dev->values[AX25_VALUES_T2]; ax25->t3 = ax25_dev->values[AX25_VALUES_T3]; ax25->n2 = ax25_dev->values[AX25_VALUES_N2]; ax25->paclen = ax25_dev->values[AX25_VALUES_PACLEN]; ax25->idle = ax25_dev->values[AX25_VALUES_IDLE]; ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF]; if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) { ax25->modulus = AX25_EMODULUS; ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW]; } else { ax25->modulus = AX25_MODULUS; ax25->window = ax25_dev->values[AX25_VALUES_WINDOW]; } } else { ax25->rtt = AX25_DEF_T1 / 2; ax25->t1 = AX25_DEF_T1; ax25->t2 = AX25_DEF_T2; ax25->t3 = AX25_DEF_T3; ax25->n2 = AX25_DEF_N2; ax25->paclen = AX25_DEF_PACLEN; ax25->idle = AX25_DEF_IDLE; ax25->backoff = AX25_DEF_BACKOFF; if (AX25_DEF_AXDEFMODE) { ax25->modulus = AX25_EMODULUS; ax25->window = AX25_DEF_EWINDOW; } else { ax25->modulus = AX25_MODULUS; ax25->window = AX25_DEF_WINDOW; } }}/* * Create an empty AX.25 control block. */ax25_cb *ax25_create_cb(void){ ax25_cb *ax25; if ((ax25 = kmalloc(sizeof(*ax25), GFP_ATOMIC)) == NULL) return NULL; MOD_INC_USE_COUNT; memset(ax25, 0x00, sizeof(*ax25)); skb_queue_head_init(&ax25->write_queue); skb_queue_head_init(&ax25->frag_queue); skb_queue_head_init(&ax25->ack_queue); skb_queue_head_init(&ax25->reseq_queue); init_timer(&ax25->timer); init_timer(&ax25->t1timer); init_timer(&ax25->t2timer); init_timer(&ax25->t3timer); init_timer(&ax25->idletimer); ax25_fillin_cb(ax25, NULL); ax25->state = AX25_STATE_0; return ax25;}/* * Handling for system calls applied via the various interfaces to an * AX25 socket object */static int ax25_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen){ struct sock *sk = sock->sk; struct net_device *dev; char devname[IFNAMSIZ]; int opt; if (level != SOL_AX25) return -ENOPROTOOPT; if (optlen < sizeof(int)) return -EINVAL; if (get_user(opt, (int *)optval)) return -EFAULT; switch (optname) { case AX25_WINDOW: if (sk->protinfo.ax25->modulus == AX25_MODULUS) { if (opt < 1 || opt > 7) return -EINVAL; } else { if (opt < 1 || opt > 63) return -EINVAL; } sk->protinfo.ax25->window = opt; return 0; case AX25_T1: if (opt < 1) return -EINVAL; sk->protinfo.ax25->rtt = (opt * HZ) / 2; sk->protinfo.ax25->t1 = opt * HZ; return 0; case AX25_T2: if (opt < 1) return -EINVAL; sk->protinfo.ax25->t2 = opt * HZ; return 0; case AX25_N2: if (opt < 1 || opt > 31) return -EINVAL; sk->protinfo.ax25->n2 = opt; return 0; case AX25_T3: if (opt < 1) return -EINVAL; sk->protinfo.ax25->t3 = opt * HZ; return 0; case AX25_IDLE: if (opt < 0) return -EINVAL; sk->protinfo.ax25->idle = opt * 60 * HZ; return 0; case AX25_BACKOFF: if (opt < 0 || opt > 2) return -EINVAL; sk->protinfo.ax25->backoff = opt; return 0; case AX25_EXTSEQ: sk->protinfo.ax25->modulus = opt ? AX25_EMODULUS : AX25_MODULUS; return 0; case AX25_PIDINCL: sk->protinfo.ax25->pidincl = opt ? 1 : 0; return 0; case AX25_IAMDIGI: sk->protinfo.ax25->iamdigi = opt ? 1 : 0; return 0; case AX25_PACLEN: if (opt < 16 || opt > 65535) return -EINVAL; sk->protinfo.ax25->paclen = opt; return 0; case SO_BINDTODEVICE: if (optlen > IFNAMSIZ) optlen=IFNAMSIZ; if (copy_from_user(devname, optval, optlen)) return -EFAULT; dev = dev_get_by_name(devname); if (dev == NULL) return -ENODEV; if (sk->type == SOCK_SEQPACKET && (sock->state != SS_UNCONNECTED || sk->state == TCP_LISTEN)) return -EADDRNOTAVAIL; sk->protinfo.ax25->ax25_dev = ax25_dev_ax25dev(dev); ax25_fillin_cb(sk->protinfo.ax25, sk->protinfo.ax25->ax25_dev); return 0; default: return -ENOPROTOOPT; }}static int ax25_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen){ struct sock *sk = sock->sk; struct ax25_dev *ax25_dev; char devname[IFNAMSIZ]; void *valptr; int val = 0; int maxlen, length; if (level != SOL_AX25) return -ENOPROTOOPT; if (get_user(maxlen, optlen)) return -EFAULT; if (maxlen < 1) return -EFAULT; valptr = (void *) &val; length = min_t(unsigned int, maxlen, sizeof(int)); switch (optname) { case AX25_WINDOW: val = sk->protinfo.ax25->window; break; case AX25_T1: val = sk->protinfo.ax25->t1 / HZ; break; case AX25_T2: val = sk->protinfo.ax25->t2 / HZ; break; case AX25_N2: val = sk->protinfo.ax25->n2; break; case AX25_T3: val = sk->protinfo.ax25->t3 / HZ; break; case AX25_IDLE: val = sk->protinfo.ax25->idle / (60 * HZ); break; case AX25_BACKOFF: val = sk->protinfo.ax25->backoff; break; case AX25_EXTSEQ: val = (sk->protinfo.ax25->modulus == AX25_EMODULUS); break; case AX25_PIDINCL: val = sk->protinfo.ax25->pidincl; break; case AX25_IAMDIGI: val = sk->protinfo.ax25->iamdigi; break; case AX25_PACLEN: val = sk->protinfo.ax25->paclen; break; case SO_BINDTODEVICE: ax25_dev = sk->protinfo.ax25->ax25_dev; if (ax25_dev != NULL && ax25_dev->dev != NULL) { strncpy(devname, ax25_dev->dev->name, IFNAMSIZ); length = min_t(unsigned int, strlen(ax25_dev->dev->name)+1, maxlen); devname[length-1] = '\0'; } else { *devname = '\0'; length = 1; } valptr = (void *) devname; break; default: return -ENOPROTOOPT; } if (put_user(length, optlen)) return -EFAULT; return copy_to_user(optval, valptr, length) ? -EFAULT : 0;}static int ax25_listen(struct socket *sock, int backlog){ struct sock *sk = sock->sk; if (sk->type == SOCK_SEQPACKET && sk->state != TCP_LISTEN) { sk->max_ack_backlog = backlog; sk->state = TCP_LISTEN; return 0; } return -EOPNOTSUPP;}int ax25_create(struct socket *sock, int protocol){ struct sock *sk; ax25_cb *ax25; switch (sock->type) { case SOCK_DGRAM: if (protocol == 0 || protocol == PF_AX25) protocol = AX25_P_TEXT; break; case SOCK_SEQPACKET: switch (protocol) { case 0: case PF_AX25: /* For CLX */ protocol = AX25_P_TEXT; break; case AX25_P_SEGMENT:#ifdef CONFIG_INET case AX25_P_ARP: case AX25_P_IP:#endif#ifdef CONFIG_NETROM case AX25_P_NETROM:#endif#ifdef CONFIG_ROSE case AX25_P_ROSE:#endif return -ESOCKTNOSUPPORT;#ifdef CONFIG_NETROM_MODULE case AX25_P_NETROM: if (ax25_protocol_is_registered(AX25_P_NETROM)) return -ESOCKTNOSUPPORT;#endif#ifdef CONFIG_ROSE_MODULE case AX25_P_ROSE: if (ax25_protocol_is_registered(AX25_P_ROSE)) return -ESOCKTNOSUPPORT;#endif default: break; } break; case SOCK_RAW: break; default: return -ESOCKTNOSUPPORT; } if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1)) == NULL) return -ENOMEM; if ((ax25 = ax25_create_cb()) == NULL) { sk_free(sk); return -ENOMEM; } sock_init_data(sock, sk); sk->destruct = ax25_free_sock; sock->ops = &ax25_proto_ops; sk->protocol = protocol; ax25->sk = sk; sk->protinfo.ax25 = ax25; return 0;}struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev){ struct sock *sk; ax25_cb *ax25; if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1)) == NULL) return NULL; if ((ax25 = ax25_create_cb()) == NULL) { sk_free(sk); return NULL; } switch (osk->type) { case SOCK_DGRAM: break; case SOCK_SEQPACKET: break; default: sk_free(sk); ax25_free_cb(ax25); return NULL; } sock_init_data(NULL, sk); sk->destruct = ax25_free_sock; sk->type = osk->type; sk->socket = osk->socket; sk->priority = osk->priority; sk->protocol = osk->protocol; sk->rcvbuf = osk->rcvbuf; sk->sndbuf = osk->sndbuf; sk->debug = osk->debug; sk->state = TCP_ESTABLISHED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -