static int 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: if (dev_to_hdlc(dev)->proto != &proto) return -EINVAL; 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; if ((result = attach_hdlc_protocol(dev, &proto, 0))) return result; dev->type = ARPHRD_X25; netif_dormant_off(dev); return 0; } return -EINVAL; }
static int most_nd_open(struct net_device *dev) { struct net_dev_context *nd = netdev_priv(dev); int ret = 0; mutex_lock(&probe_disc_mt); if (most_start_channel(nd->iface, nd->rx.ch_id, &comp)) { netdev_err(dev, "most_start_channel() failed\n"); ret = -EBUSY; goto unlock; } if (most_start_channel(nd->iface, nd->tx.ch_id, &comp)) { netdev_err(dev, "most_start_channel() failed\n"); most_stop_channel(nd->iface, nd->rx.ch_id, &comp); ret = -EBUSY; goto unlock; } netif_carrier_off(dev); if (is_valid_ether_addr(dev->dev_addr)) netif_dormant_off(dev); else netif_dormant_on(dev); netif_wake_queue(dev); if (nd->iface->request_netinfo) nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, on_netinfo); unlock: mutex_unlock(&probe_disc_mt); return ret; }
/** * on_netinfo - callback for HDM to be informed about HW's MAC * @param iface - most interface instance * @param link_stat - link status * @param mac_addr - MAC address */ static void on_netinfo(struct most_interface *iface, unsigned char link_stat, unsigned char *mac_addr) { struct net_dev_context *nd; struct net_device *dev; const u8 *m = mac_addr; nd = get_net_dev_hold(iface); if (!nd) return; dev = nd->dev; if (link_stat) netif_carrier_on(dev); else netif_carrier_off(dev); if (m && is_valid_ether_addr(m)) { if (!is_valid_ether_addr(dev->dev_addr)) { netdev_info(dev, "set mac %02x-%02x-%02x-%02x-%02x-%02x\n", m[0], m[1], m[2], m[3], m[4], m[5]); ether_addr_copy(dev->dev_addr, m); netif_dormant_off(dev); } else if (!ether_addr_equal(dev->dev_addr, m)) { netdev_warn(dev, "reject mac %02x-%02x-%02x-%02x-%02x-%02x\n", m[0], m[1], m[2], m[3], m[4], m[5]); } } dev_put(nd->dev); }
/* opa_vnic_process_vema_config - process vema configuration updates */ void opa_vnic_process_vema_config(struct opa_vnic_adapter *adapter) { struct __opa_veswport_info *info = &adapter->info; struct rdma_netdev *rn = netdev_priv(adapter->netdev); u8 port_num[OPA_VESW_MAX_NUM_DEF_PORT] = { 0 }; struct net_device *netdev = adapter->netdev; u8 i, port_count = 0; u16 port_mask; /* If the base_mac_addr is changed, update the interface mac address */ if (memcmp(info->vport.base_mac_addr, adapter->vema_mac_addr, ARRAY_SIZE(info->vport.base_mac_addr))) { struct sockaddr saddr; memcpy(saddr.sa_data, info->vport.base_mac_addr, ARRAY_SIZE(info->vport.base_mac_addr)); mutex_lock(&adapter->lock); eth_mac_addr(netdev, &saddr); memcpy(adapter->vema_mac_addr, info->vport.base_mac_addr, ETH_ALEN); mutex_unlock(&adapter->lock); } rn->set_id(netdev, info->vesw.vesw_id); /* Handle MTU limit change */ rtnl_lock(); netdev->max_mtu = max_t(unsigned int, info->vesw.eth_mtu_non_vlan, netdev->min_mtu); if (netdev->mtu > netdev->max_mtu) dev_set_mtu(netdev, netdev->max_mtu); rtnl_unlock(); /* Update flow to default port redirection table */ port_mask = info->vesw.def_port_mask; for (i = 0; i < OPA_VESW_MAX_NUM_DEF_PORT; i++) { if (port_mask & 1) port_num[port_count++] = i; port_mask >>= 1; } /* * Build the flow table. Flow table is required when destination LID * is not available. Up to OPA_VNIC_FLOW_TBL_SIZE flows supported. * Each flow need a default port number to get its dlid from the * u_ucast_dlid array. */ for (i = 0; i < OPA_VNIC_FLOW_TBL_SIZE; i++) adapter->flow_tbl[i] = port_count ? port_num[i % port_count] : OPA_VNIC_INVALID_PORT; /* Operational state can only be DROP_ALL or FORWARDING */ if (info->vport.config_state == OPA_VNIC_STATE_FORWARDING) { info->vport.oper_state = OPA_VNIC_STATE_FORWARDING; netif_dormant_off(netdev); } else { info->vport.oper_state = OPA_VNIC_STATE_DROP_ALL; netif_dormant_on(netdev); } }
static int raw_eth_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, old_qlen; switch (ifr->ifr_settings.type) { case IF_GET_PROTO: if (dev_to_hdlc(dev)->proto != &proto) return -EINVAL; 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, 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(dev, new_settings.encoding, new_settings.parity); if (result) return result; result = attach_hdlc_protocol(dev, &proto, sizeof(raw_hdlc_proto)); if (result) return result; memcpy(hdlc->state, &new_settings, size); old_qlen = dev->tx_queue_len; ether_setup(dev); dev->tx_queue_len = old_qlen; random_ether_addr(dev->dev_addr); netif_dormant_off(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; }
static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev) { /* Have to respect userspace enforced dormant state * of real device, also must allow supplicant running * on VLAN device */ if (dev->operstate == IF_OPER_DORMANT) netif_dormant_on(vlandev); else netif_dormant_off(vlandev); if (netif_carrier_ok(dev)) { if (!netif_carrier_ok(vlandev)) netif_carrier_on(vlandev); } else { if (netif_carrier_ok(vlandev)) netif_carrier_off(vlandev); } }
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; }
static int cisco_rx(struct sk_buff *skb) { struct net_device *dev = skb->dev; hdlc_device *hdlc = dev_to_hdlc(dev); struct cisco_state *st = state(hdlc); struct hdlc_header *data = (struct hdlc_header*)skb->data; struct cisco_packet *cisco_data; struct in_device *in_dev; __be32 addr, mask; u32 ack; if (skb->len < sizeof(struct hdlc_header)) goto rx_error; if (data->address != CISCO_MULTICAST && data->address != CISCO_UNICAST) goto rx_error; switch (ntohs(data->protocol)) { case CISCO_SYS_INFO: /* Packet is not needed, drop it. */ dev_kfree_skb_any(skb); return NET_RX_SUCCESS; case CISCO_KEEPALIVE: if ((skb->len != sizeof(struct hdlc_header) + CISCO_PACKET_LEN) && (skb->len != sizeof(struct hdlc_header) + CISCO_BIG_PACKET_LEN)) { netdev_info(dev, "Invalid length of Cisco control packet (%d bytes)\n", skb->len); goto rx_error; } cisco_data = (struct cisco_packet*)(skb->data + sizeof (struct hdlc_header)); switch (ntohl (cisco_data->type)) { case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); addr = 0; mask = ~cpu_to_be32(0); /* is the mask correct? */ if (in_dev != NULL) { struct in_ifaddr **ifap = &in_dev->ifa_list; while (*ifap != NULL) { if (strcmp(dev->name, (*ifap)->ifa_label) == 0) { addr = (*ifap)->ifa_local; mask = (*ifap)->ifa_mask; break; } ifap = &(*ifap)->ifa_next; } cisco_keepalive_send(dev, CISCO_ADDR_REPLY, addr, mask); } rcu_read_unlock(); dev_kfree_skb_any(skb); return NET_RX_SUCCESS; case CISCO_ADDR_REPLY: netdev_info(dev, "Unexpected Cisco IP address reply\n"); goto rx_error; case CISCO_KEEPALIVE_REQ: spin_lock(&st->lock); st->rxseq = ntohl(cisco_data->par1); ack = ntohl(cisco_data->par2); if (ack && (ack == st->txseq || /* our current REQ may be in transit */ ack == st->txseq - 1)) { st->last_poll = jiffies; if (!st->up) { u32 sec, min, hrs, days; sec = ntohl(cisco_data->time) / 1000; min = sec / 60; sec -= min * 60; hrs = min / 60; min -= hrs * 60; days = hrs / 24; hrs -= days * 24; netdev_info(dev, "Link up (peer uptime %ud%uh%um%us)\n", days, hrs, min, sec); netif_dormant_off(dev); st->up = 1; } } spin_unlock(&st->lock); dev_kfree_skb_any(skb); return NET_RX_SUCCESS; } /* switch (keepalive type) */ } /* switch (protocol) */ netdev_info(dev, "Unsupported protocol %x\n", ntohs(data->protocol)); dev_kfree_skb_any(skb); return NET_RX_DROP; rx_error: dev->stats.rx_errors++; /* Mark error */ dev_kfree_skb_any(skb); return NET_RX_DROP; }
/* SCA: RCR+ must supply id, len and data SCN: RCR- must supply code, id, len and data STA: RTR must supply id SCJ: RUC must supply CP packet len and data */ static void ppp_cp_event(struct net_device *dev, u16 pid, u16 event, u8 code, u8 id, unsigned int len, const void *data) { int old_state, action; struct ppp *ppp = get_ppp(dev); struct proto *proto = get_proto(dev, pid); old_state = proto->state; BUG_ON(old_state >= STATES); BUG_ON(event >= EVENTS); #if DEBUG_STATE printk(KERN_DEBUG "%s: %s ppp_cp_event(%s) %s ...\n", dev->name, proto_name(pid), event_names[event], state_names[proto->state]); #endif action = cp_table[event][old_state]; proto->state = action & STATE_MASK; if (action & (SCR | STR)) /* set Configure-Req/Terminate-Req timer */ mod_timer(&proto->timer, proto->timeout = jiffies + ppp->req_timeout * HZ); if (action & ZRC) proto->restart_counter = 0; if (action & IRC) proto->restart_counter = (proto->state == STOPPING) ? ppp->term_retries : ppp->cr_retries; if (action & SCR) /* send Configure-Request */ ppp_tx_cp(dev, pid, CP_CONF_REQ, proto->cr_id = ++ppp->seq, 0, NULL); if (action & SCA) /* send Configure-Ack */ ppp_tx_cp(dev, pid, CP_CONF_ACK, id, len, data); if (action & SCN) /* send Configure-Nak/Reject */ ppp_tx_cp(dev, pid, code, id, len, data); if (action & STR) /* send Terminate-Request */ ppp_tx_cp(dev, pid, CP_TERM_REQ, ++ppp->seq, 0, NULL); if (action & STA) /* send Terminate-Ack */ ppp_tx_cp(dev, pid, CP_TERM_ACK, id, 0, NULL); if (action & SCJ) /* send Code-Reject */ ppp_tx_cp(dev, pid, CP_CODE_REJ, ++ppp->seq, len, data); if (old_state != OPENED && proto->state == OPENED) { printk(KERN_INFO "%s: %s up\n", dev->name, proto_name(pid)); if (pid == PID_LCP) { netif_dormant_off(dev); ppp_cp_event(dev, PID_IPCP, START, 0, 0, 0, NULL); ppp_cp_event(dev, PID_IPV6CP, START, 0, 0, 0, NULL); ppp->last_pong = jiffies; mod_timer(&proto->timer, proto->timeout = jiffies + ppp->keepalive_interval * HZ); } } if (old_state == OPENED && proto->state != OPENED) { printk(KERN_INFO "%s: %s down\n", dev->name, proto_name(pid)); if (pid == PID_LCP) { netif_dormant_on(dev); ppp_cp_event(dev, PID_IPCP, STOP, 0, 0, 0, NULL); ppp_cp_event(dev, PID_IPV6CP, STOP, 0, 0, 0, NULL); } } if (old_state != CLOSED && proto->state == CLOSED) del_timer(&proto->timer); #if DEBUG_STATE printk(KERN_DEBUG "%s: %s ppp_cp_event(%s) ... %s\n", dev->name, proto_name(pid), event_names[event], state_names[proto->state]); #endif }
static int cisco_rx(struct sk_buff *skb) { struct net_device *dev = skb->dev; hdlc_device *hdlc = dev_to_hdlc(dev); hdlc_header *data = (hdlc_header*)skb->data; cisco_packet *cisco_data; struct in_device *in_dev; u32 addr, mask; if (skb->len < sizeof(hdlc_header)) goto rx_error; if (data->address != CISCO_MULTICAST && data->address != CISCO_UNICAST) goto rx_error; switch(ntohs(data->protocol)) { case CISCO_SYS_INFO: /* Packet is not needed, drop it. */ dev_kfree_skb_any(skb); return NET_RX_SUCCESS; case CISCO_KEEPALIVE: if (skb->len != sizeof(hdlc_header) + CISCO_PACKET_LEN && skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) { printk(KERN_INFO "%s: Invalid length of Cisco " "control packet (%d bytes)\n", dev->name, skb->len); goto rx_error; } cisco_data = (cisco_packet*)(skb->data + sizeof(hdlc_header)); switch(ntohl (cisco_data->type)) { case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ in_dev = dev->ip_ptr; addr = 0; mask = ~0; /* is the mask correct? */ if (in_dev != NULL) { struct in_ifaddr **ifap = &in_dev->ifa_list; while (*ifap != NULL) { if (strcmp(dev->name, (*ifap)->ifa_label) == 0) { addr = (*ifap)->ifa_local; mask = (*ifap)->ifa_mask; break; } ifap = &(*ifap)->ifa_next; } cisco_keepalive_send(dev, CISCO_ADDR_REPLY, addr, mask); } dev_kfree_skb_any(skb); return NET_RX_SUCCESS; case CISCO_ADDR_REPLY: printk(KERN_INFO "%s: Unexpected Cisco IP address " "reply\n", dev->name); goto rx_error; case CISCO_KEEPALIVE_REQ: hdlc->state.cisco.rxseq = ntohl(cisco_data->par1); if (hdlc->state.cisco.request_sent && ntohl(cisco_data->par2)==hdlc->state.cisco.txseq) { hdlc->state.cisco.last_poll = jiffies; if (!hdlc->state.cisco.up) { u32 sec, min, hrs, days; sec = ntohl(cisco_data->time) / 1000; min = sec / 60; sec -= min * 60; hrs = min / 60; min -= hrs * 60; days = hrs / 24; hrs -= days * 24; printk(KERN_INFO "%s: Link up (peer " "uptime %ud%uh%um%us)\n", dev->name, days, hrs, min, sec); netif_dormant_off(dev); hdlc->state.cisco.up = 1; } } dev_kfree_skb_any(skb); return NET_RX_SUCCESS; } /* switch(keepalive type) */ } /* switch(protocol) */ printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name, data->protocol); dev_kfree_skb_any(skb); return NET_RX_DROP; rx_error: hdlc->stats.rx_errors++; /* Mark error */ dev_kfree_skb_any(skb); return NET_RX_DROP; }