📄 af_ipx.c
字号:
sg = (struct sockaddr_ipx *)&rt.rt_gateway; st = (struct sockaddr_ipx *)&rt.rt_dst; if(!(rt.rt_flags & RTF_GATEWAY)) return (-EINVAL); /* Direct routes are fixed */ if(sg->sipx_family != AF_IPX) return (-EINVAL); if(st->sipx_family != AF_IPX) return (-EINVAL); switch(cmd) { case SIOCDELRT: return (ipxrtr_delete(st->sipx_network)); case SIOCADDRT: { struct ipx_route_definition f; f.ipx_network=st->sipx_network; f.ipx_router_network=sg->sipx_network; memcpy(f.ipx_router_node, sg->sipx_node, IPX_NODE_LEN); return (ipxrtr_create(&f)); } default: return (-EINVAL); }}static const char *ipx_frame_name(unsigned short frame){ switch(ntohs(frame)) { case ETH_P_IPX: return ("EtherII"); case ETH_P_802_2: return ("802.2"); case ETH_P_SNAP: return ("SNAP"); case ETH_P_802_3: return ("802.3"); case ETH_P_TR_802_2: return ("802.2TR"); default: return ("None"); }}static const char *ipx_device_name(ipx_interface *intrfc){ return (intrfc->if_internal ? "Internal" : (intrfc->if_dev ? intrfc->if_dev->name : "Unknown"));}/* Called from proc fs */static int ipx_interface_get_info(char *buffer, char **start, off_t offset, int length){ ipx_interface *i; off_t begin = 0, pos = 0; int len = 0; /* Theory.. Keep printing in the same place until we pass offset */ len += sprintf(buffer,"%-11s%-15s%-9s%-11s%s", "Network", "Node_Address", "Primary", "Device", "Frame_Type");#ifdef IPX_REFCNT_DEBUG len += sprintf(buffer + len, " refcnt");#endif strcat(buffer+len++, "\n"); spin_lock_bh(&ipx_interfaces_lock); for(i = ipx_interfaces; i != NULL; i = i->if_next) { len += sprintf(buffer+len, "%08lX ", (long unsigned int)ntohl(i->if_netnum)); len += sprintf(buffer+len,"%02X%02X%02X%02X%02X%02X ", i->if_node[0], i->if_node[1], i->if_node[2], i->if_node[3], i->if_node[4], i->if_node[5]); len += sprintf(buffer+len, "%-9s", (i == ipx_primary_net) ? "Yes" : "No"); len += sprintf(buffer+len, "%-11s", ipx_device_name(i)); len += sprintf(buffer+len, "%-9s", ipx_frame_name(i->if_dlink_type));#ifdef IPX_REFCNT_DEBUG len += sprintf(buffer+len,"%6d",atomic_read(&i->refcnt));#endif strcat(buffer+len++, "\n"); /* Are we still dumping unwanted data then discard the record */ pos = begin + len; if(pos < offset) { len = 0; /* Keep dumping into the buffer start */ begin = pos; } if(pos > offset + length) /* We have dumped enough */ break; } spin_unlock_bh(&ipx_interfaces_lock); /* The data in question runs from begin to begin+len */ *start = buffer + (offset - begin); /* Start of wanted data */ len -= (offset - begin); /* Remove unwanted header data from length */ if(len > length) len = length; /* Remove unwanted tail data from length */ return (len);}static int ipx_get_info(char *buffer, char **start, off_t offset, int length){ struct sock *s; ipx_interface *i; off_t begin = 0, pos = 0; int len = 0; /* Theory.. Keep printing in the same place until we pass offset */#ifdef CONFIG_IPX_INTERN len += sprintf(buffer,"%-28s%-28s%-10s%-10s%-7s%s\n", "Local_Address",#else len += sprintf(buffer,"%-15s%-28s%-10s%-10s%-7s%s\n", "Local_Address",#endif /* CONFIG_IPX_INTERN */ "Remote_Address", "Tx_Queue", "Rx_Queue", "State", "Uid"); spin_lock_bh(&ipx_interfaces_lock); for(i = ipx_interfaces; i != NULL; i = i->if_next) { ipxitf_hold(i); spin_lock_bh(&i->if_sklist_lock); for(s = i->if_sklist; s != NULL; s = s->next) {#ifdef CONFIG_IPX_INTERN len += sprintf(buffer+len, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ", (unsigned long) htonl(s->protinfo.af_ipx.intrfc->if_netnum), s->protinfo.af_ipx.node[0], s->protinfo.af_ipx.node[1], s->protinfo.af_ipx.node[2], s->protinfo.af_ipx.node[3], s->protinfo.af_ipx.node[4], s->protinfo.af_ipx.node[5], htons(s->protinfo.af_ipx.port));#else len += sprintf(buffer+len,"%08lX:%04X ", (unsigned long)htonl(i->if_netnum), htons(s->protinfo.af_ipx.port));#endif /* CONFIG_IPX_INTERN */ if(s->state != TCP_ESTABLISHED) len += sprintf(buffer+len, "%-28s", "Not_Connected"); else { len += sprintf(buffer+len, "%08lX:%02X%02X%02X%02X%02X%02X:%04X ", (unsigned long) htonl(s->protinfo.af_ipx.dest_addr.net), s->protinfo.af_ipx.dest_addr.node[0], s->protinfo.af_ipx.dest_addr.node[1], s->protinfo.af_ipx.dest_addr.node[2], s->protinfo.af_ipx.dest_addr.node[3], s->protinfo.af_ipx.dest_addr.node[4], s->protinfo.af_ipx.dest_addr.node[5], htons(s->protinfo.af_ipx.dest_addr.sock)); } len += sprintf(buffer+len,"%08X %08X ", atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc)); len += sprintf(buffer+len,"%02X %03d\n", s->state, SOCK_INODE(s->socket)->i_uid); pos = begin + len; if(pos < offset) { len = 0; begin = pos; } if(pos > offset + length) /* We have dumped enough */ break; } spin_unlock_bh(&i->if_sklist_lock); ipxitf_put(i); } spin_unlock_bh(&ipx_interfaces_lock); /* The data in question runs from begin to begin+len */ *start = buffer + (offset-begin); len -= (offset - begin); if(len > length) len = length; return (len);}static int ipx_rt_get_info(char *buffer, char **start, off_t offset, int length){ ipx_route *rt; off_t begin = 0, pos = 0; int len = 0; len += sprintf(buffer,"%-11s%-13s%s\n", "Network", "Router_Net", "Router_Node"); read_lock_bh(&ipx_routes_lock); for(rt = ipx_routes; rt != NULL; rt = rt->ir_next) { len += sprintf(buffer+len,"%08lX ", (long unsigned int) ntohl(rt->ir_net)); if(rt->ir_routed) { len += sprintf(buffer+len,"%08lX %02X%02X%02X%02X%02X%02X\n", (long unsigned int) ntohl(rt->ir_intrfc->if_netnum), rt->ir_router_node[0], rt->ir_router_node[1], rt->ir_router_node[2], rt->ir_router_node[3], rt->ir_router_node[4], rt->ir_router_node[5]); } else { len += sprintf(buffer+len, "%-13s%s\n", "Directly", "Connected"); } pos = begin + len; if(pos < offset) { len = 0; begin = pos; } if(pos > offset + length) break; } read_unlock_bh(&ipx_routes_lock); *start = buffer + (offset - begin); len -= (offset - begin); if(len > length) len = length; return (len);}/**************************************************************************\* ** Handling for system calls applied via the various interfaces to an ** IPX socket object. ** *\**************************************************************************/static int ipx_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen){ struct sock *sk; int err, opt; sk = sock->sk; if(optlen != sizeof(int)) return (-EINVAL); err = get_user(opt, (unsigned int *)optval); if(err) return (err); switch(level) { case SOL_IPX: switch(optname) { case IPX_TYPE: sk->protinfo.af_ipx.type = opt; return (0); default: return (-ENOPROTOOPT); } break; default: return (-ENOPROTOOPT); }}static int ipx_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen){ struct sock *sk; int val=0; int len; sk = sock->sk; switch(level) { case SOL_IPX: switch(optname) { case IPX_TYPE: val = sk->protinfo.af_ipx.type; break; default: return (-ENOPROTOOPT); } break; default: return (-ENOPROTOOPT); } if(get_user(len, optlen)) return (-EFAULT); len = min(len, sizeof(int)); if(put_user(len, optlen)) return (-EFAULT); if(copy_to_user(optval, &val, len)) return (-EFAULT); return (0);}static int ipx_create(struct socket *sock, int protocol){ struct sock *sk; switch(sock->type) { case SOCK_DGRAM: sk = sk_alloc(PF_IPX, GFP_KERNEL, 1); if(sk == NULL) return (-ENOMEM); sock->ops = &ipx_dgram_ops; break; case SOCK_SEQPACKET: /* * From this point on SPX sockets are handled * by af_spx.c and the methods replaced. */ if(spx_family_ops) return (spx_family_ops->create(sock,protocol)); /* Fall through if SPX is not loaded */ case SOCK_STREAM: /* Allow higher levels to piggyback */ default: return (-ESOCKTNOSUPPORT); }#ifdef IPX_REFCNT_DEBUG atomic_inc(&ipx_sock_nr); printk(KERN_DEBUG "IPX socket %p created, now we have %d alive\n", sk, atomic_read(&ipx_sock_nr));#endif sock_init_data(sock, sk); sk->destruct = NULL; sk->no_check = 1; /* Checksum off by default */ MOD_INC_USE_COUNT; return (0);}static int ipx_release(struct socket *sock){ struct sock *sk = sock->sk; if(sk == NULL) return (0); if(!sk->dead) sk->state_change(sk); sk->dead = 1; sock->sk = NULL; ipx_destroy_socket(sk); if(sock->type == SOCK_DGRAM) MOD_DEC_USE_COUNT; return (0);}/* caller must hold a referente to intrfc */static unsigned short ipx_first_free_socketnum(ipx_interface *intrfc){ unsigned short socketNum = intrfc->if_sknum; spin_lock_bh(&intrfc->if_sklist_lock); if(socketNum < IPX_MIN_EPHEMERAL_SOCKET) socketNum = IPX_MIN_EPHEMERAL_SOCKET; while(__ipxitf_find_socket(intrfc, ntohs(socketNum)) != NULL) { if(socketNum > IPX_MAX_EPHEMERAL_SOCKET) socketNum = IPX_MIN_EPHEMERAL_SOCKET; else socketNum++; } spin_unlock_bh(&intrfc->if_sklist_lock); intrfc->if_sknum = socketNum; return (ntohs(socketNum));}static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len){ struct sock *sk; ipx_interface *intrfc; struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr; int ret; sk = sock->sk; if(sk->zapped == 0) return (-EINVAL); if(addr_len != sizeof(struct sockaddr_ipx)) return (-EINVAL); intrfc = ipxitf_find_using_net(addr->sipx_network); if(intrfc == NULL) return (-EADDRNOTAVAIL); if(addr->sipx_port == 0) { addr->sipx_port = ipx_first_free_socketnum(intrfc); ret = -EINVAL; if(addr->sipx_port == 0) goto out; } /* protect IPX system stuff like routing/sap */ ret = -EACCES; if(ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET && !capable(CAP_NET_ADMIN)) goto out; sk->protinfo.af_ipx.port = addr->sipx_port;#ifdef CONFIG_IPX_INTERN if(intrfc == ipx_internal_net) { /* The source address is to be set explicitly if the * socket is to be bound on the internal network. If a * node number 0 was specified, the default is used. */ ret = -EINVAL; if(memcmp(addr->sipx_node,ipx_broadcast_node,IPX_NODE_LEN) == 0) goto out; if(memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN) == 0) { memcpy(sk->protinfo.af_ipx.node, intrfc->if_node, IPX_NODE_LEN); } else { memcpy(sk->protinfo.af_ipx.node, addr->sipx_node, IPX_NODE_LEN); } ret = -EADDRINUSE; if(ipxitf_find_internal_socket(intrfc, sk->protinfo.af_ipx.node, sk->protinfo.af_ipx.port) != NULL) { SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n", ntohs((int)addr->sipx_port)); goto out; } } else { /* Source addresses are easy. It must be our * network:node pair for an interface routed to IPX * with the ipx routing ioctl() */ memcpy(sk->protinfo.af_ipx.node, intrfc->if_node, IPX_NODE_LEN); ret = -EADDRINUSE; if(ipxitf_find_socket(intrfc, addr->sipx_port) != NULL) { SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n", ntohs((int)addr->sipx_port)); goto out; } }#else /* !def CONFIG_IPX_INTERN */ /* Source addresses are easy. It must be our network:node pair for an interface routed to IPX with the ipx routing ioctl() */ ret = -EADDRINUSE; if(ipxitf_find_socket(intrfc, addr->sipx_port) != NULL) { SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n", ntohs((int)addr->sipx_port)); goto out; }#endif /* CONFIG_IPX_INTERN */ ipxitf_insert_socket(intrfc, sk); sk->zapped = 0; SOCK_DEBUG(sk, "IPX: bound socket 0x%04X.\n", ntohs(addr->sipx_port) ); ret = 0;out: ipxitf_put(intrfc); return ret;}static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags){ struct sock *sk = sock->sk; struct sockaddr_ipx *addr; sk->state = TCP_CLOSE; sock->state = SS_UNCONNECTED; if(addr_len != sizeof(*addr)) return (-EINVAL); addr = (struct sockaddr_ipx *)uaddr; /* put the autobinding in */ if(sk->protinfo.af_ipx.port == 0) { struct sockaddr_ipx uaddr; int ret; uaddr.sipx_port = 0; uaddr.sipx_network = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -