static int bnep_sock_create(struct net *net, struct socket *sock, int protocol, int kern) { struct sock *sk; BT_DBG("sock %p", sock); if (sock->type != SOCK_RAW) return -ESOCKTNOSUPPORT; sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, kern); if (!sk) return -ENOMEM; sock_init_data(sock, sk); sock->ops = &bnep_sock_ops; sock->state = SS_UNCONNECTED; sock_reset_flag(sk, SOCK_ZAPPED); sk->sk_protocol = protocol; sk->sk_state = BT_OPEN; bt_sock_link(&bnep_sk_list, sk); return 0; }
/* * Do all connect socket setups that can be done AF independent. */ static inline void dccp_connect_init(struct sock *sk) { struct dccp_sock *dp = dccp_sk(sk); struct dst_entry *dst = __sk_dst_get(sk); struct inet_connection_sock *icsk = inet_csk(sk); sk->sk_err = 0; sock_reset_flag(sk, SOCK_DONE); dccp_sync_mss(sk, dst_mtu(dst)); dccp_update_gss(sk, dp->dccps_iss); /* * SWL and AWL are initially adjusted so that they are not less than * the initial Sequence Numbers received and sent, respectively: * SWL := max(GSR + 1 - floor(W/4), ISR), * AWL := max(GSS - W' + 1, ISS). * These adjustments MUST be applied only at the beginning of the * connection. */ dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss)); icsk->icsk_retransmits = 0; init_timer(&dp->dccps_xmit_timer); dp->dccps_xmit_timer.data = (unsigned long)sk; dp->dccps_xmit_timer.function = dccp_write_xmit_timer; }
static void sock_disable_timestamp(struct sock *sk) { if (sock_flag(sk, SOCK_TIMESTAMP)) { sock_reset_flag(sk, SOCK_TIMESTAMP); net_disable_timestamp(); } }
void *app_glue_create_socket(int family,int type) { struct timeval tv; struct socket *sock = NULL; if(sock_create_kern(family,type,0,&sock)) { ipaugenblick_log(IPAUGENBLICK_LOG_ERR,"cannot create socket %s %d\n",__FILE__,__LINE__); return NULL; } tv.tv_sec = -1; tv.tv_usec = 0; if(sock_setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(char *)&tv,sizeof(tv))) { ipaugenblick_log(IPAUGENBLICK_LOG_ERR,"%s %d cannot set notimeout option\n",__FILE__,__LINE__); } tv.tv_sec = -1; tv.tv_usec = 0; if(sock_setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(char *)&tv,sizeof(tv))) { ipaugenblick_log(IPAUGENBLICK_LOG_ERR,"%s %d cannot set notimeout option\n",__FILE__,__LINE__); } if(type != SOCK_STREAM) { if(sock->sk) { sock_reset_flag(sock->sk,SOCK_USE_WRITE_QUEUE); sock->sk->sk_data_ready = app_glue_sock_readable; sock->sk->sk_write_space = app_glue_sock_write_space; app_glue_sock_write_space(sock->sk); } } return sock; }
/* * This callback function is invoked when a new connection can be accepted on socket. * It looks up the parent (listening) socket for the newly established connection * and inserts it into the accept queue * which is processed in periodic function app_glue_periodic * Paramters: a pointer to struct sock * Returns: void * */ static void app_glue_sock_wakeup(struct sock *sk) { struct sock *sock; struct tcp_sock *tp; tp = tcp_sk(sk); sock = __inet_lookup_listener(&init_net/*sk->sk_net*/, &tcp_hashinfo, sk->sk_daddr, sk->sk_dport/*__be16 sport*/, sk->sk_rcv_saddr, ntohs(tp->inet_conn.icsk_inet.inet_sport),//sk->sk_num/*const unsigned short hnum*/, sk->sk_bound_dev_if); if(sock) { if(sock->sk_socket->accept_queue_present) { return; } sock_hold(sock); sock->sk_socket->accept_queue_present = 1; TAILQ_INSERT_TAIL(&accept_ready_socket_list_head,sock->sk_socket,accept_queue_entry); } else { struct tcp_sock *tp; tp = tcp_sk(sk); app_glue_sock_write_space(sk); //ipaugenblick_log(IPAUGENBLICK_LOG_INFO,"%s %d %x %d %x %d %d \n",__FILE__,__LINE__,sk->sk_daddr,sk->sk_dport,sk->sk_rcv_saddr,sk->sk_num,tp->inet_conn.icsk_inet.inet_sport); } sock_reset_flag(sk,SOCK_USE_WRITE_QUEUE); sk->sk_data_ready = app_glue_sock_readable; sk->sk_write_space = app_glue_sock_write_space; sk->sk_error_report = app_glue_sock_error_report; sk->sk_destruct= app_glue_sock_error_report; }
static int cmtp_sock_create(struct socket *sock, int protocol) { struct sock *sk; BT_DBG("sock %p", sock); if (sock->type != SOCK_RAW) return -ESOCKTNOSUPPORT; sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &cmtp_proto, 1); if (!sk) return -ENOMEM; sock_init_data(sock, sk); sock->ops = &cmtp_sock_ops; sock->state = SS_UNCONNECTED; sock_reset_flag(sk, SOCK_ZAPPED); sk->sk_protocol = protocol; sk->sk_state = BT_OPEN; return 0; }
static int setup_sock_common(struct sock *sk, struct cpt_sock_image *si, loff_t pos, struct cpt_context *ctx) { struct timeval tmptv; if (sk->sk_socket) { sk->sk_socket->flags = si->cpt_ssflags; sk->sk_socket->state = si->cpt_sstate; } sk->sk_reuse = si->cpt_reuse; sk->sk_shutdown = si->cpt_shutdown; sk->sk_userlocks = si->cpt_userlocks; sk->sk_no_check = si->cpt_no_check; sock_reset_flag(sk, SOCK_DBG); if (si->cpt_debug) sock_set_flag(sk, SOCK_DBG); sock_reset_flag(sk, SOCK_RCVTSTAMP); if (si->cpt_rcvtstamp) sock_set_flag(sk, SOCK_RCVTSTAMP); sock_reset_flag(sk, SOCK_LOCALROUTE); if (si->cpt_localroute) sock_set_flag(sk, SOCK_LOCALROUTE); sk->sk_protocol = si->cpt_protocol; sk->sk_err = si->cpt_err; sk->sk_err_soft = si->cpt_err_soft; sk->sk_priority = si->cpt_priority; sk->sk_rcvlowat = si->cpt_rcvlowat; sk->sk_rcvtimeo = si->cpt_rcvtimeo; if (si->cpt_rcvtimeo == CPT_NULL) sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; sk->sk_sndtimeo = si->cpt_sndtimeo; if (si->cpt_sndtimeo == CPT_NULL) sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; sk->sk_rcvbuf = si->cpt_rcvbuf; sk->sk_sndbuf = si->cpt_sndbuf; sk->sk_bound_dev_if = si->cpt_bound_dev_if; sk->sk_flags = si->cpt_flags; sk->sk_lingertime = si->cpt_lingertime; if (si->cpt_lingertime == CPT_NULL) sk->sk_lingertime = MAX_SCHEDULE_TIMEOUT; sk->sk_peercred.pid = si->cpt_peer_pid; sk->sk_peercred.uid = si->cpt_peer_uid; sk->sk_peercred.gid = si->cpt_peer_gid; cpt_timeval_import(&tmptv, si->cpt_stamp); sk->sk_stamp = timeval_to_ktime(tmptv); return 0; }
/** * llc_ui_bind - bind a socket to a specific address. * @sock: Socket to bind an address to. * @uaddr: Address the user wants the socket bound to. * @addrlen: Length of the uaddr structure. * * Bind a socket to a specific address. For llc a user is able to bind to * a specific sap only or mac + sap. If the user only specifies a sap and * a null dmac (all zeros) the user is attempting to bind to an entire * sap. This will stop anyone else on the local system from using that * sap. If someone else has a mac + sap open the bind to null + sap will * fail. * If the user desires to bind to a specific mac + sap, it is possible to * have multiple sap connections via multiple macs. * Bind and autobind for that matter must enforce the correct sap usage * otherwise all hell will break loose. * Returns: 0 upon success, negative otherwise. */ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) { struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr; struct sock *sk = sock->sk; struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap; int rc = -EINVAL; dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap); if (!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)) goto out; rc = -EAFNOSUPPORT; if (addr->sllc_family != AF_LLC) goto out; if (!addr->sllc_sap) { rc = -EUSERS; addr->sllc_sap = llc_ui_autoport(); if (!addr->sllc_sap) goto out; } sap = llc_sap_find(addr->sllc_sap); if (!sap) { sap = llc_sap_open(addr->sllc_sap, NULL); rc = -EBUSY; /* some other network layer is using the sap */ if (!sap) goto out; } else { struct llc_addr laddr, daddr; struct sock *ask; memset(&laddr, 0, sizeof(laddr)); memset(&daddr, 0, sizeof(daddr)); /* * FIXME: check if the the address is multicast, * only SOCK_DGRAM can do this. */ memcpy(laddr.mac, addr->sllc_mac, IFHWADDRLEN); laddr.lsap = addr->sllc_sap; rc = -EADDRINUSE; /* mac + sap clash. */ ask = llc_lookup_established(sap, &daddr, &laddr); if (ask) { sock_put(ask); goto out; } } llc->laddr.lsap = addr->sllc_sap; memcpy(llc->laddr.mac, addr->sllc_mac, IFHWADDRLEN); memcpy(&llc->addr, addr, sizeof(llc->addr)); /* assign new connection to its SAP */ llc_sap_add_socket(sap, sk); sock_reset_flag(sk, SOCK_ZAPPED); rc = 0; out: return rc; }
static int MksckCreate(struct net *net, struct socket *sock, int protocol, int kern) { struct sock *sk; uid_t currentUid = current_euid(); if (!(currentUid == 0 || currentUid == Mvpkm_vmwareUid)) { pr_warn("MksckCreate: rejected from process %s " \ "tgid=%d, pid=%d euid:%d.\n", current->comm, task_tgid_vnr(current), task_pid_vnr(current), currentUid); return -EPERM; } if (!sock) return -EINVAL; if (protocol) return -EPROTONOSUPPORT; switch (sock->type) { case SOCK_DGRAM: sock->ops = &mksckDgramOps; break; default: return -ESOCKTNOSUPPORT; } sock->state = SS_UNCONNECTED; sk = sk_alloc(net, mksckFamilyOps.family, GFP_KERNEL, &mksckProto); if (!sk) return -ENOMEM; sock_init_data(sock, sk); sk->sk_type = SOCK_DGRAM; sk->sk_destruct = MksckSkDestruct; sk->sk_backlog_rcv = MksckBacklogRcv; sk->sk_protinfo = NULL; sock_reset_flag(sk, SOCK_DONE); return 0; }
int dccp_disconnect(struct sock *sk, int flags) { struct inet_connection_sock *icsk = inet_csk(sk); struct inet_sock *inet = inet_sk(sk); struct dccp_sock *dp = dccp_sk(sk); int err = 0; const int old_state = sk->sk_state; if (old_state != DCCP_CLOSED) dccp_set_state(sk, DCCP_CLOSED); /* * This corresponds to the ABORT function of RFC793, sec. 3.8 * TCP uses a RST segment, DCCP a Reset packet with Code 2, "Aborted". */ if (old_state == DCCP_LISTEN) { inet_csk_listen_stop(sk); } else if (dccp_need_reset(old_state)) { dccp_send_reset(sk, DCCP_RESET_CODE_ABORTED); sk->sk_err = ECONNRESET; } else if (old_state == DCCP_REQUESTING) sk->sk_err = ECONNRESET; dccp_clear_xmit_timers(sk); ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); dp->dccps_hc_rx_ccid = NULL; __skb_queue_purge(&sk->sk_receive_queue); __skb_queue_purge(&sk->sk_write_queue); if (sk->sk_send_head != NULL) { __kfree_skb(sk->sk_send_head); sk->sk_send_head = NULL; } inet->inet_dport = 0; if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) inet_reset_saddr(sk); sk->sk_shutdown = 0; sock_reset_flag(sk, SOCK_DONE); icsk->icsk_backoff = 0; inet_csk_delack_init(sk); __sk_dst_reset(sk); WARN_ON(inet->inet_num && !icsk->icsk_bind_hash); sk->sk_error_report(sk); return err; }
/* * Find which interface to use. */ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) { ax25_uid_assoc *user; ax25_route *ax25_rt; int err = 0; ax25_route_lock_use(); ax25_rt = ax25_get_route(addr, NULL); if (!ax25_rt) { ax25_route_lock_unuse(); return -EHOSTUNREACH; } if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) { err = -EHOSTUNREACH; goto put; } user = ax25_findbyuid(current_euid()); if (user) { ax25->source_addr = user->call; ax25_uid_put(user); } else { if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) { err = -EPERM; goto put; } ax25->source_addr = *(ax25_address *)ax25->ax25_dev->dev->dev_addr; } if (ax25_rt->digipeat != NULL) { ax25->digipeat = kmemdup(ax25_rt->digipeat, sizeof(ax25_digi), GFP_ATOMIC); if (ax25->digipeat == NULL) { err = -ENOMEM; goto put; } ax25_adjust_path(addr, ax25->digipeat); } if (ax25->sk != NULL) { bh_lock_sock(ax25->sk); sock_reset_flag(ax25->sk, SOCK_ZAPPED); bh_unlock_sock(ax25->sk); } put: ax25_route_lock_unuse(); return err; }
/** * llc_ui_accept - accept a new incoming connection. * @sock: Socket which connections arrive on. * @newsock: Socket to move incoming connection to. * @flags: User specified operational flags. * * Accept a new incoming connection. * Returns 0 upon success, negative otherwise. */ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags) { struct sock *sk = sock->sk, *newsk; struct llc_sock *llc, *newllc; struct sk_buff *skb; int rc = -EOPNOTSUPP; dprintk("%s: accepting on %02X\n", __FUNCTION__, llc_sk(sk)->laddr.lsap); lock_sock(sk); if (sk->sk_type != SOCK_STREAM) goto out; rc = -EINVAL; if (sock->state != SS_UNCONNECTED || sk->sk_state != TCP_LISTEN) goto out; /* wait for a connection to arrive. */ rc = llc_ui_wait_for_data(sk, sk->sk_rcvtimeo); if (rc) goto out; dprintk("%s: got a new connection on %02X\n", __FUNCTION__, llc_sk(sk)->laddr.lsap); skb = skb_dequeue(&sk->sk_receive_queue); rc = -EINVAL; if (!skb->sk) goto frees; rc = 0; newsk = skb->sk; /* attach connection to a new socket. */ llc_ui_sk_init(newsock, newsk); sock_reset_flag(newsk, SOCK_ZAPPED); newsk->sk_state = TCP_ESTABLISHED; newsock->state = SS_CONNECTED; llc = llc_sk(sk); newllc = llc_sk(newsk); memcpy(&newllc->addr, &llc->addr, sizeof(newllc->addr)); newllc->link = llc_ui_next_link_no(newllc->laddr.lsap); /* put original socket back into a clean listen state. */ sk->sk_state = TCP_LISTEN; sk->sk_ack_backlog--; skb->sk = NULL; dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__, llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap); frees: kfree_skb(skb); out: release_sock(sk); return rc; }
static int vsock_shutdown(struct socket *sock, int mode) { int err; struct sock *sk; /* User level uses SHUT_RD (0) and SHUT_WR (1), but the kernel uses * RCV_SHUTDOWN (1) and SEND_SHUTDOWN (2), so we must increment mode * here like the other address families do. Note also that the * increment makes SHUT_RDWR (2) into RCV_SHUTDOWN | SEND_SHUTDOWN (3), * which is what we want. */ mode++; if ((mode & ~SHUTDOWN_MASK) || !mode) return -EINVAL; /* If this is a STREAM socket and it is not connected then bail out * immediately. If it is a DGRAM socket then we must first kick the * socket so that it wakes up from any sleeping calls, for example * recv(), and then afterwards return the error. */ sk = sock->sk; if (sock->state == SS_UNCONNECTED) { err = -ENOTCONN; if (sk->sk_type == SOCK_STREAM) return err; } else { sock->state = SS_DISCONNECTING; err = 0; } /* Receive and send shutdowns are treated alike. */ mode = mode & (RCV_SHUTDOWN | SEND_SHUTDOWN); if (mode) { lock_sock(sk); sk->sk_shutdown |= mode; sk->sk_state_change(sk); release_sock(sk); if (sk->sk_type == SOCK_STREAM) { sock_reset_flag(sk, SOCK_DONE); vsock_send_shutdown(sk, mode); } } return err; }
/* * Do all connect socket setups that can be done AF independent. */ static inline void dccp_connect_init(struct sock *sk) { struct dccp_sock *dp = dccp_sk(sk); struct dst_entry *dst = __sk_dst_get(sk); struct inet_connection_sock *icsk = inet_csk(sk); sk->sk_err = 0; sock_reset_flag(sk, SOCK_DONE); dccp_sync_mss(sk, dst_mtu(dst)); /* Initialise GAR as per 8.5; AWL/AWH are set in dccp_transmit_skb() */ dp->dccps_gar = dp->dccps_iss; icsk->icsk_retransmits = 0; }
void pfq_free_sk_filter(struct sk_filter *filter) { struct sock sk; int rv; sock_init_data(NULL, &sk); sk.sk_filter = NULL; atomic_set(&sk.sk_omem_alloc, 0); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) sock_reset_flag(&sk, SOCK_FILTER_LOCKED); #endif sk.sk_filter = filter; if ((rv = sk_detach_filter(&sk))) pr_devel("[PFQ] BPF: sk_detach_filter error: (%d)!\n", rv); }
/* * Do all connect socket setups that can be done AF independent. */ static inline void dccp_connect_init(struct sock *sk) { struct dst_entry *dst = __sk_dst_get(sk); struct inet_connection_sock *icsk = inet_csk(sk); sk->sk_err = 0; sock_reset_flag(sk, SOCK_DONE); dccp_sync_mss(sk, dst_mtu(dst)); /* * FIXME: set dp->{dccps_swh,dccps_swl}, with * something like dccp_inc_seq */ icsk->icsk_retransmits = 0; }
int dccp_disconnect(struct sock *sk, int flags) { struct inet_connection_sock *icsk = inet_csk(sk); struct inet_sock *inet = inet_sk(sk); int err = 0; const int old_state = sk->sk_state; if (old_state != DCCP_CLOSED) dccp_set_state(sk, DCCP_CLOSED); if (old_state == DCCP_LISTEN) { inet_csk_listen_stop(sk); } else if (dccp_need_reset(old_state)) { dccp_send_reset(sk, DCCP_RESET_CODE_ABORTED); sk->sk_err = ECONNRESET; } else if (old_state == DCCP_REQUESTING) sk->sk_err = ECONNRESET; dccp_clear_xmit_timers(sk); __skb_queue_purge(&sk->sk_receive_queue); __skb_queue_purge(&sk->sk_write_queue); if (sk->sk_send_head != NULL) { __kfree_skb(sk->sk_send_head); sk->sk_send_head = NULL; } inet->dport = 0; if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) inet_reset_saddr(sk); sk->sk_shutdown = 0; sock_reset_flag(sk, SOCK_DONE); icsk->icsk_backoff = 0; inet_csk_delack_init(sk); __sk_dst_reset(sk); WARN_ON(inet->num && !icsk->icsk_bind_hash); sk->sk_error_report(sk); return err; }
int dccp_disconnect(struct sock *sk, int flags) { struct inet_connection_sock *icsk = inet_csk(sk); struct inet_sock *inet = inet_sk(sk); int err = 0; const int old_state = sk->sk_state; if (old_state != DCCP_CLOSED) dccp_set_state(sk, DCCP_CLOSED); /* ABORT function of RFC793 */ if (old_state == DCCP_LISTEN) { inet_csk_listen_stop(sk); /* FIXME: do the active reset thing */ } else if (old_state == DCCP_REQUESTING) sk->sk_err = ECONNRESET; dccp_clear_xmit_timers(sk); __skb_queue_purge(&sk->sk_receive_queue); if (sk->sk_send_head != NULL) { __kfree_skb(sk->sk_send_head); sk->sk_send_head = NULL; } inet->dport = 0; if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) inet_reset_saddr(sk); sk->sk_shutdown = 0; sock_reset_flag(sk, SOCK_DONE); icsk->icsk_backoff = 0; inet_csk_delack_init(sk); __sk_dst_reset(sk); BUG_TRAP(!inet->num || icsk->icsk_bind_hash); sk->sk_error_report(sk); return err; }
struct sk_filter * pfq_alloc_sk_filter(struct sock_fprog *fprog) { struct sock sk; int rv; sock_init_data(NULL, &sk); sk.sk_filter = NULL; atomic_set(&sk.sk_omem_alloc, 0); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) sock_reset_flag(&sk, SOCK_FILTER_LOCKED); #endif pr_devel("[PFQ] BPF: new fprog (len %d)\n", fprog->len); if ((rv = sk_attach_filter(fprog, &sk))) { pr_devel("[PFQ] BPF: sk_attach_filter error: (%d)!\n", rv); return NULL; } return sk.sk_filter; }
/* * Do all connect socket setups that can be done AF independent. */ int dccp_connect(struct sock *sk) { struct sk_buff *skb; struct dccp_sock *dp = dccp_sk(sk); struct dst_entry *dst = __sk_dst_get(sk); struct inet_connection_sock *icsk = inet_csk(sk); sk->sk_err = 0; sock_reset_flag(sk, SOCK_DONE); dccp_sync_mss(sk, dst_mtu(dst)); /* do not connect if feature negotiation setup fails */ if (dccp_feat_finalise_settings(dccp_sk(sk))) return -EPROTO; /* Initialise GAR as per 8.5; AWL/AWH are set in dccp_transmit_skb() */ dp->dccps_gar = dp->dccps_iss; skb = alloc_skb(sk->sk_prot->max_header, sk->sk_allocation); if (unlikely(skb == NULL)) return -ENOBUFS; /* Reserve space for headers. */ skb_reserve(skb, sk->sk_prot->max_header); DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST; dccp_transmit_skb(sk, dccp_skb_entail(sk, skb)); DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS); /* Timer for repeating the REQUEST until an answer. */ icsk->icsk_retransmits = 0; inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, DCCP_RTO_MAX); return 0; }
/** * llc_ui_autobind - automatically bind a socket to a sap * @sock: socket to bind * @addr: address to connect to * * Used by llc_ui_connect and llc_ui_sendmsg when the user hasn't * specifically used llc_ui_bind to bind to an specific address/sap * * Returns: 0 upon success, negative otherwise. */ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) { struct sock *sk = sock->sk; struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap; int rc = -EINVAL; if (!sock_flag(sk, SOCK_ZAPPED)) goto out; rc = -ENODEV; if (sk->sk_bound_dev_if) { llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if); if (llc->dev && addr->sllc_arphrd != llc->dev->type) { dev_put(llc->dev); llc->dev = NULL; } } else llc->dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd); if (!llc->dev) goto out; rc = -EUSERS; llc->laddr.lsap = llc_ui_autoport(); if (!llc->laddr.lsap) goto out; rc = -EBUSY; /* some other network layer is using the sap */ sap = llc_sap_open(llc->laddr.lsap, NULL); if (!sap) goto out; memcpy(llc->laddr.mac, llc->dev->dev_addr, IFHWADDRLEN); memcpy(&llc->addr, addr, sizeof(llc->addr)); /* assign new connection to its SAP */ llc_sap_add_socket(sap, sk); sock_reset_flag(sk, SOCK_ZAPPED); rc = 0; out: return rc; }
struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio) { struct sock *sk; sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto); if (!sk) return NULL; sock_init_data(sock, sk); INIT_LIST_HEAD(&bt_sk(sk)->accept_q); sk->sk_destruct = l2cap_sock_destruct; sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT); sock_reset_flag(sk, SOCK_ZAPPED); sk->sk_protocol = proto; sk->sk_state = BT_OPEN; setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk); bt_sock_link(&l2cap_sk_list, sk); return sk; }
/** * xs_tcp_connect_worker - connect a TCP socket to a remote endpoint * @args: RPC transport to connect * * Invoked by a work queue tasklet. */ static void xs_tcp_connect_worker(void *args) { struct rpc_xprt *xprt = (struct rpc_xprt *)args; struct socket *sock = xprt->sock; int err, status = -EIO; if (xprt->shutdown || xprt->addr.sin_port == 0) goto out; dprintk("RPC: xs_tcp_connect_worker for xprt %p\n", xprt); if (!xprt->sock) { /* start from scratch */ if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { dprintk("RPC: can't create TCP transport socket (%d).\n", -err); goto out; } xs_reclassify_socket(sock); if (xs_bind(xprt, sock)) { sock_release(sock); goto out; } } else /* "close" the socket, preserving the local port */ xs_tcp_reuse_connection(xprt); if (!xprt->inet) { struct sock *sk = sock->sk; write_lock_bh(&sk->sk_callback_lock); sk->sk_user_data = xprt; xprt->old_data_ready = sk->sk_data_ready; xprt->old_state_change = sk->sk_state_change; xprt->old_write_space = sk->sk_write_space; sk->sk_data_ready = xs_tcp_data_ready; sk->sk_state_change = xs_tcp_state_change; sk->sk_write_space = xs_tcp_write_space; sk->sk_allocation = GFP_ATOMIC; /* socket options */ sk->sk_userlocks |= SOCK_BINDPORT_LOCK; sock_reset_flag(sk, SOCK_LINGER); tcp_sk(sk)->linger2 = 0; tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; xprt_clear_connected(xprt); /* Reset to new socket */ xprt->sock = sock; xprt->inet = sk; write_unlock_bh(&sk->sk_callback_lock); } /* Tell the socket layer to start connecting... */ xprt->stat.connect_count++; xprt->stat.connect_start = jiffies; status = kernel_connect(sock, (struct sockaddr *) &xprt->addr, sizeof(xprt->addr), O_NONBLOCK); dprintk("RPC: %p connect status %d connected %d sock state %d\n", xprt, -status, xprt_connected(xprt), sock->sk->sk_state); if (status < 0) { switch (status) { case -EINPROGRESS: case -EALREADY: goto out_clear; case -ECONNREFUSED: case -ECONNRESET: /* retry with existing socket, after a delay */ break; case -ENETUNREACH: status = -ENOTCONN; break; default: /* get rid of existing socket, and retry */ xs_close(xprt); break; } } out: xprt_wake_pending_tasks(xprt, status); out_clear: xprt_clear_connecting(xprt); }
struct sock *sk_clone(struct sock *sk, const gfp_t priority) { struct sock *newsk = sk_alloc(sk->sk_family, priority, sk->sk_prot, 0); if (newsk != NULL) { struct sk_filter *filter; memcpy(newsk, sk, sk->sk_prot->obj_size); /* SANITY */ sk_node_init(&newsk->sk_node); sock_lock_init(newsk); bh_lock_sock(newsk); atomic_set(&newsk->sk_rmem_alloc, 0); atomic_set(&newsk->sk_wmem_alloc, 0); atomic_set(&newsk->sk_omem_alloc, 0); skb_queue_head_init(&newsk->sk_receive_queue); skb_queue_head_init(&newsk->sk_write_queue); rwlock_init(&newsk->sk_dst_lock); rwlock_init(&newsk->sk_callback_lock); newsk->sk_dst_cache = NULL; newsk->sk_wmem_queued = 0; newsk->sk_forward_alloc = 0; newsk->sk_send_head = NULL; newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL; newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK; sock_reset_flag(newsk, SOCK_DONE); skb_queue_head_init(&newsk->sk_error_queue); filter = newsk->sk_filter; if (filter != NULL) sk_filter_charge(newsk, filter); if (sk->sk_create_child) sk->sk_create_child(sk, newsk); if (unlikely(xfrm_sk_clone_policy(newsk))) { /* It is still raw copy of parent, so invalidate * destructor and make plain sk_free() */ newsk->sk_destruct = NULL; sk_free(newsk); newsk = NULL; goto out; } newsk->sk_err = 0; newsk->sk_priority = 0; atomic_set(&newsk->sk_refcnt, 2); /* * Increment the counter in the same struct proto as the master * sock (sk_refcnt_debug_inc uses newsk->sk_prot->socks, that * is the same as sk->sk_prot->socks, as this field was copied * with memcpy). * * This _changes_ the previous behaviour, where * tcp_create_openreq_child always was incrementing the * equivalent to tcp_prot->socks (inet_sock_nr), so this have * to be taken into account in all callers. -acme */ sk_refcnt_debug_inc(newsk); newsk->sk_socket = NULL; newsk->sk_sleep = NULL; if (newsk->sk_prot->sockets_allocated) atomic_inc(newsk->sk_prot->sockets_allocated); } out: return newsk; }
//start_listening void moon_listen(void) { //For test purposes moonraker_socket_t *listen; listen = kmalloc(sizeof(moonraker_socket_t),GFP_KERNEL); listen->proto = kmalloc(sizeof(moonraker_proto_t),GFP_KERNEL); listen->proto->name = kmalloc(5,GFP_KERNEL); listen->ip = 2130706433; listen->port = 80; listen->proto->defer_accept=0; listen->keepalive_timeout=0; listen->ack_pingpong=1; listen->max_backlog=2048; listen->defer_accept=1; strcpy(listen->proto->name,"http"); //end for test purpose struct sockaddr_in sin; struct socket *sock = NULL; struct sock *sk; struct tcp_sock *tp; struct inet_connection_sock *icsk; moonraker_proto_t *proto = listen->proto; u16 port = listen->port; u32 addr = listen->ip; //127.0.0.1 int err = 0; err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); if (err) { printk(KERN_ERR "Moonraker: error %d creating socket.\n", err); goto error; } sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(addr); sin.sin_port = htons(port); sk = sock->sk; icsk = inet_csk(sk); sk->sk_reuse = 1; sock_set_flag(sk, SOCK_URGINLINE); err = sock->ops->bind(sock, (struct sockaddr*)&sin, sizeof(sin)); if (err){ printk(KERN_ERR "Moonraker: error %d binding socket. This means that probably some other process is (or was a short time ago) using addr %d\n",err,sin.sin_addr.s_addr); goto error; } tp = tcp_sk(sk); printk("listen sk accept_queue: %d.\n",!reqsk_queue_empty(&icsk->icsk_accept_queue)); icsk->icsk_ack.pingpong = listen->ack_pingpong; sock_reset_flag(sk, SOCK_LINGER); sk->sk_lingertime = 0; tp->linger2 = listen->keepalive_timeout * HZ; if (proto->defer_accept && !listen->keepalive_timeout && listen->defer_accept) icsk->icsk_accept_queue.rskq_defer_accept = 1; err = sock->ops->listen(sock, listen->max_backlog); if (err) { printk(KERN_ERR "Moonraker: error %d listening on socket.\n", err); goto error; } printk(KERN_NOTICE "Moonraker: thread %d listens on %s://%d.%d.%d.%d:%d.\n", 1, proto->name, HIPQUAD(addr), port); // return sock; return; error: if (sock) sock_release(sock); return; return NULL; }
int sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen) { struct sock *sk=sock->sk; struct sk_filter *filter; int val; int valbool; struct linger ling; int ret = 0; /* * Options without arguments */ #ifdef SO_DONTLINGER /* Compatibility item... */ if (optname == SO_DONTLINGER) { lock_sock(sk); sock_reset_flag(sk, SOCK_LINGER); release_sock(sk); return 0; } #endif if(optlen<sizeof(int)) return(-EINVAL); if (get_user(val, (int __user *)optval)) return -EFAULT; valbool = val?1:0; lock_sock(sk); switch(optname) { case SO_DEBUG: if(val && !capable(CAP_NET_ADMIN)) { ret = -EACCES; } else if (valbool) sock_set_flag(sk, SOCK_DBG); else sock_reset_flag(sk, SOCK_DBG); break; case SO_REUSEADDR: sk->sk_reuse = valbool; break; case SO_TYPE: case SO_ERROR: ret = -ENOPROTOOPT; break; case SO_DONTROUTE: if (valbool) sock_set_flag(sk, SOCK_LOCALROUTE); else sock_reset_flag(sk, SOCK_LOCALROUTE); break; case SO_BROADCAST: sock_valbool_flag(sk, SOCK_BROADCAST, valbool); break; case SO_SNDBUF: /* Don't error on this BSD doesn't and if you think about it this is right. Otherwise apps have to play 'guess the biggest size' games. RCVBUF/SNDBUF are treated in BSD as hints */ if (val > sysctl_wmem_max) val = sysctl_wmem_max; set_sndbuf: sk->sk_userlocks |= SOCK_SNDBUF_LOCK; if ((val * 2) < SOCK_MIN_SNDBUF) sk->sk_sndbuf = SOCK_MIN_SNDBUF; else sk->sk_sndbuf = val * 2; /* * Wake up sending tasks if we * upped the value. */ sk->sk_write_space(sk); break; case SO_SNDBUFFORCE: if (!capable(CAP_NET_ADMIN)) { ret = -EPERM; break; } goto set_sndbuf; case SO_RCVBUF: /* Don't error on this BSD doesn't and if you think about it this is right. Otherwise apps have to play 'guess the biggest size' games. RCVBUF/SNDBUF are treated in BSD as hints */ if (val > sysctl_rmem_max) val = sysctl_rmem_max; set_rcvbuf: sk->sk_userlocks |= SOCK_RCVBUF_LOCK; /* * We double it on the way in to account for * "struct sk_buff" etc. overhead. Applications * assume that the SO_RCVBUF setting they make will * allow that much actual data to be received on that * socket. * * Applications are unaware that "struct sk_buff" and * other overheads allocate from the receive buffer * during socket buffer allocation. * * And after considering the possible alternatives, * returning the value we actually used in getsockopt * is the most desirable behavior. */ if ((val * 2) < SOCK_MIN_RCVBUF) sk->sk_rcvbuf = SOCK_MIN_RCVBUF; else sk->sk_rcvbuf = val * 2; break; case SO_RCVBUFFORCE: if (!capable(CAP_NET_ADMIN)) { ret = -EPERM; break; } goto set_rcvbuf; case SO_KEEPALIVE: #ifdef CONFIG_INET if (sk->sk_protocol == IPPROTO_TCP) tcp_set_keepalive(sk, valbool); #endif sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool); break; case SO_OOBINLINE: sock_valbool_flag(sk, SOCK_URGINLINE, valbool); break; case SO_NO_CHECK: sk->sk_no_check = valbool; break; case SO_PRIORITY: if ((val >= 0 && val <= 6) || capable(CAP_NET_ADMIN)) sk->sk_priority = val; else ret = -EPERM; break; case SO_LINGER: if(optlen<sizeof(ling)) { ret = -EINVAL; /* 1003.1g */ break; } if (copy_from_user(&ling,optval,sizeof(ling))) { ret = -EFAULT; break; } if (!ling.l_onoff) sock_reset_flag(sk, SOCK_LINGER); else { #if (BITS_PER_LONG == 32) if ((unsigned int)ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ) sk->sk_lingertime = MAX_SCHEDULE_TIMEOUT; else #endif sk->sk_lingertime = (unsigned int)ling.l_linger * HZ; sock_set_flag(sk, SOCK_LINGER); } break; case SO_BSDCOMPAT: sock_warn_obsolete_bsdism("setsockopt"); break; case SO_PASSCRED: if (valbool) set_bit(SOCK_PASSCRED, &sock->flags); else clear_bit(SOCK_PASSCRED, &sock->flags); break; case SO_TIMESTAMP: if (valbool) { sock_set_flag(sk, SOCK_RCVTSTAMP); sock_enable_timestamp(sk); } else sock_reset_flag(sk, SOCK_RCVTSTAMP); break; case SO_RCVLOWAT: if (val < 0) val = INT_MAX; sk->sk_rcvlowat = val ? : 1; break; case SO_RCVTIMEO: ret = sock_set_timeout(&sk->sk_rcvtimeo, optval, optlen); break; case SO_SNDTIMEO: ret = sock_set_timeout(&sk->sk_sndtimeo, optval, optlen); break; #ifdef CONFIG_NETDEVICES case SO_BINDTODEVICE: { char devname[IFNAMSIZ]; /* Sorry... */ if (!capable(CAP_NET_RAW)) { ret = -EPERM; break; } /* Bind this socket to a particular device like "eth0", * as specified in the passed interface name. If the * name is "" or the option length is zero the socket * is not bound. */ if (!valbool) { sk->sk_bound_dev_if = 0; } else { if (optlen > IFNAMSIZ - 1) optlen = IFNAMSIZ - 1; memset(devname, 0, sizeof(devname)); if (copy_from_user(devname, optval, optlen)) { ret = -EFAULT; break; } /* Remove any cached route for this socket. */ sk_dst_reset(sk); if (devname[0] == '\0') { sk->sk_bound_dev_if = 0; } else { struct net_device *dev = dev_get_by_name(devname); if (!dev) { ret = -ENODEV; break; } sk->sk_bound_dev_if = dev->ifindex; dev_put(dev); } } break; } #endif case SO_ATTACH_FILTER: ret = -EINVAL; if (optlen == sizeof(struct sock_fprog)) { struct sock_fprog fprog; ret = -EFAULT; if (copy_from_user(&fprog, optval, sizeof(fprog))) break; ret = sk_attach_filter(&fprog, sk); } break; case SO_DETACH_FILTER: spin_lock_bh(&sk->sk_lock.slock); filter = sk->sk_filter; if (filter) { sk->sk_filter = NULL; spin_unlock_bh(&sk->sk_lock.slock); sk_filter_release(sk, filter); break; } spin_unlock_bh(&sk->sk_lock.slock); ret = -ENONET; break; /* We implement the SO_SNDLOWAT etc to not be settable (1003.1g 5.3) */ default: ret = -ENOPROTOOPT; break; } release_sock(sk); return ret; }
struct sock *__vsock_create(struct net *net, struct socket *sock, struct sock *parent, gfp_t priority, unsigned short type, int kern) { struct sock *sk; struct vsock_sock *psk; struct vsock_sock *vsk; sk = sk_alloc(net, AF_VSOCK, priority, &vsock_proto, kern); if (!sk) return NULL; sock_init_data(sock, sk); /* sk->sk_type is normally set in sock_init_data, but only if sock is * non-NULL. We make sure that our sockets always have a type by * setting it here if needed. */ if (!sock) sk->sk_type = type; vsk = vsock_sk(sk); vsock_addr_init(&vsk->local_addr, VMADDR_CID_ANY, VMADDR_PORT_ANY); vsock_addr_init(&vsk->remote_addr, VMADDR_CID_ANY, VMADDR_PORT_ANY); sk->sk_destruct = vsock_sk_destruct; sk->sk_backlog_rcv = vsock_queue_rcv_skb; sock_reset_flag(sk, SOCK_DONE); INIT_LIST_HEAD(&vsk->bound_table); INIT_LIST_HEAD(&vsk->connected_table); vsk->listener = NULL; INIT_LIST_HEAD(&vsk->pending_links); INIT_LIST_HEAD(&vsk->accept_queue); vsk->rejected = false; vsk->sent_request = false; vsk->ignore_connecting_rst = false; vsk->peer_shutdown = 0; psk = parent ? vsock_sk(parent) : NULL; if (parent) { vsk->trusted = psk->trusted; vsk->owner = get_cred(psk->owner); vsk->connect_timeout = psk->connect_timeout; } else { vsk->trusted = capable(CAP_NET_ADMIN); vsk->owner = get_current_cred(); vsk->connect_timeout = VSOCK_DEFAULT_CONNECT_TIMEOUT; } if (transport->init(vsk, psk) < 0) { sk_free(sk); return NULL; } if (sock) vsock_insert_unbound(vsk); return sk; }