void unregister_hdlc_device(struct net_device *dev) { rtnl_lock(); hdlc_proto_detach(dev_to_hdlc(dev)); unregister_netdevice(dev); rtnl_unlock(); }
void unregister_hdlc_device(hdlc_device *hdlc) { hdlc_proto_detach(hdlc); unregister_netdev(hdlc_to_dev(hdlc)); MOD_DEC_USE_COUNT; }
int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr) { cisco_proto __user *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco; const size_t size = sizeof(cisco_proto); cisco_proto new_settings; hdlc_device *hdlc = dev_to_hdlc(dev); int result; switch (ifr->ifr_settings.type) { case IF_GET_PROTO: ifr->ifr_settings.type = IF_PROTO_CISCO; if (ifr->ifr_settings.size < size) { ifr->ifr_settings.size = size; /* data size wanted */ return -ENOBUFS; } if (copy_to_user(cisco_s, &hdlc->state.cisco.settings, size)) return -EFAULT; return 0; case IF_PROTO_CISCO: if(!capable(CAP_NET_ADMIN)) return -EPERM; if(dev->flags & IFF_UP) return -EBUSY; if (copy_from_user(&new_settings, cisco_s, size)) return -EFAULT; if (new_settings.interval < 1 || new_settings.timeout < 2) return -EINVAL; result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); if (result) return result; hdlc_proto_detach(hdlc); memcpy(&hdlc->state.cisco.settings, &new_settings, size); memset(&hdlc->proto, 0, sizeof(hdlc->proto)); hdlc->proto.start = cisco_start; hdlc->proto.stop = cisco_stop; hdlc->proto.netif_rx = cisco_rx; hdlc->proto.type_trans = cisco_type_trans; hdlc->proto.id = IF_PROTO_CISCO; dev->hard_start_xmit = hdlc->xmit; dev->hard_header = cisco_hard_header; dev->hard_header_cache = NULL; dev->type = ARPHRD_CISCO; dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->addr_len = 0; netif_dormant_on(dev); return 0; } return -EINVAL; }
int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) { raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; const size_t size = sizeof(raw_hdlc_proto); raw_hdlc_proto new_settings; hdlc_device *hdlc = dev_to_hdlc(dev); int result; switch (ifr->ifr_settings.type) { case IF_GET_PROTO: ifr->ifr_settings.type = IF_PROTO_HDLC; if (ifr->ifr_settings.size < size) { ifr->ifr_settings.size = size; /* data size wanted */ return -ENOBUFS; } if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) return -EFAULT; return 0; case IF_PROTO_HDLC: if (!capable(CAP_NET_ADMIN)) return -EPERM; if (dev->flags & IFF_UP) return -EBUSY; if (copy_from_user(&new_settings, raw_s, size)) return -EFAULT; if (new_settings.encoding == ENCODING_DEFAULT) new_settings.encoding = ENCODING_NRZ; if (new_settings.parity == PARITY_DEFAULT) new_settings.parity = PARITY_CRC16_PR1_CCITT; result = hdlc->attach(dev, new_settings.encoding, new_settings.parity); if (result) return result; hdlc_proto_detach(hdlc); memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size); memset(&hdlc->proto, 0, sizeof(hdlc->proto)); hdlc->proto.type_trans = raw_type_trans; hdlc->proto.id = IF_PROTO_HDLC; dev->hard_start_xmit = hdlc->xmit; dev->hard_header = NULL; dev->type = ARPHRD_RAWHDLC; dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->addr_len = 0; netif_dormant_off(dev); return 0; } return -EINVAL; }
int hdlc_cisco_ioctl(hdlc_device *hdlc, struct ifreq *ifr) { cisco_proto *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco; const size_t size = sizeof(cisco_proto); cisco_proto new_settings; struct net_device *dev = hdlc_to_dev(hdlc); int result; switch (ifr->ifr_settings.type) { case IF_GET_PROTO: ifr->ifr_settings.type = IF_PROTO_CISCO; if (ifr->ifr_settings.size < size) { ifr->ifr_settings.size = size; /* data size wanted */ return -ENOBUFS; } if (copy_to_user(cisco_s, &hdlc->state.cisco.settings, size)) return -EFAULT; return 0; case IF_PROTO_CISCO: if(!capable(CAP_NET_ADMIN)) return -EPERM; if(dev->flags & IFF_UP) return -EBUSY; if (copy_from_user(&new_settings, cisco_s, size)) return -EFAULT; if (new_settings.interval < 1 || new_settings.timeout < 2) return -EINVAL; result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); if (result) return result; hdlc_proto_detach(hdlc); memcpy(&hdlc->state.cisco.settings, &new_settings, size); hdlc->open = cisco_open; hdlc->stop = cisco_close; hdlc->netif_rx = cisco_rx; hdlc->proto = IF_PROTO_CISCO; dev->hard_start_xmit = hdlc->xmit; dev->hard_header = cisco_hard_header; dev->type = ARPHRD_CISCO; dev->addr_len = 0; return 0; } return -EINVAL; }
int hdlc_ppp_ioctl(hdlc_device *hdlc, struct ifreq *ifr) { struct net_device *dev = hdlc_to_dev(hdlc); int result; switch (ifr->ifr_settings.type) { case IF_GET_PROTO: ifr->ifr_settings.type = IF_PROTO_PPP; return 0; /* return protocol only, no settable parameters */ case IF_PROTO_PPP: if(!capable(CAP_NET_ADMIN)) return -EPERM; if(dev->flags & IFF_UP) return -EBUSY; /* no settable parameters */ result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); if (result) return result; hdlc_proto_detach(hdlc); memset(&hdlc->proto, 0, sizeof(hdlc->proto)); hdlc->proto.open = ppp_open; hdlc->proto.close = ppp_close; hdlc->proto.type_trans = ppp_type_trans; hdlc->proto.id = IF_PROTO_PPP; dev->hard_start_xmit = hdlc->xmit; dev->hard_header = NULL; dev->type = ARPHRD_PPP; dev->addr_len = 0; return 0; } return -EINVAL; }
int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr) { hdlc_device *hdlc = dev_to_hdlc(dev); int result; switch (ifr->ifr_settings.type) { case IF_GET_PROTO: ifr->ifr_settings.type = IF_PROTO_X25; return 0; /* return protocol only, no settable parameters */ case IF_PROTO_X25: if(!capable(CAP_NET_ADMIN)) return -EPERM; if(dev->flags & IFF_UP) return -EBUSY; result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); if (result) return result; hdlc_proto_detach(hdlc); memset(&hdlc->proto, 0, sizeof(hdlc->proto)); hdlc->proto.open = x25_open; hdlc->proto.close = x25_close; hdlc->proto.netif_rx = x25_rx; hdlc->proto.type_trans = NULL; hdlc->proto.id = IF_PROTO_X25; dev->hard_start_xmit = x25_xmit; dev->hard_header = NULL; dev->type = ARPHRD_X25; dev->addr_len = 0; netif_dormant_off(dev); return 0; } return -EINVAL; }
int hdlc_raw_eth_ioctl(hdlc_device *hdlc, struct ifreq *ifr) { raw_hdlc_proto *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; const size_t size = sizeof(raw_hdlc_proto); raw_hdlc_proto new_settings; struct net_device *dev = hdlc_to_dev(hdlc); int result; void *old_ch_mtu; int old_qlen; switch (ifr->ifr_settings.type) { case IF_GET_PROTO: ifr->ifr_settings.type = IF_PROTO_HDLC_ETH; if (ifr->ifr_settings.size < size) { ifr->ifr_settings.size = size; /* data size wanted */ return -ENOBUFS; } if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) return -EFAULT; return 0; case IF_PROTO_HDLC_ETH: if (!capable(CAP_NET_ADMIN)) return -EPERM; if (dev->flags & IFF_UP) return -EBUSY; if (copy_from_user(&new_settings, raw_s, size)) return -EFAULT; if (new_settings.encoding == ENCODING_DEFAULT) new_settings.encoding = ENCODING_NRZ; if (new_settings.parity == PARITY_DEFAULT) new_settings.parity = PARITY_CRC16_PR1_CCITT; result = hdlc->attach(hdlc, new_settings.encoding, new_settings.parity); if (result) return result; hdlc_proto_detach(hdlc); memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size); hdlc->open = NULL; hdlc->stop = NULL; hdlc->netif_rx = NULL; hdlc->type_trans = eth_type_trans; hdlc->proto = IF_PROTO_HDLC_ETH; dev->hard_start_xmit = eth_tx; old_ch_mtu = dev->change_mtu; old_qlen = dev->tx_queue_len; ether_setup(dev); dev->change_mtu = old_ch_mtu; dev->tx_queue_len = old_qlen; memcpy(dev->dev_addr, "\x00\x01", 2); get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); return 0; } return -EINVAL; }