kernels/linux-2.4.0/net/decnet/dn_nsp_in.c
/*
 * This function uses a slightly different lookup method
 * to find its sockets, since it searches on object name/number
 * rather than port numbers. Various tests are done to ensure that
 * the incoming data is in the correct format before it is queued to
 * a socket.
 */
This function uses a slightly different lookup method
to find its sockets, since it searches on object name/number
rather than port numbers. Various tests are done to ensure that
the incoming data is in the correct format before it is queued to
a socket.
This function uses a slightly different lookup method to find its sockets since it searches on object name / number rather than port numbers . Various tests are done to ensure that the incoming data is in the correct format before it is queued to a socket .
static struct sock *dn_find_listener(struct sk_buff *skb, unsigned short *reason)
{
	struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
	struct nsp_conn_init_msg *msg = (struct nsp_conn_init_msg *)skb->data;
	struct sockaddr_dn dstaddr;
	struct sockaddr_dn srcaddr;
	unsigned char type = 0;
	int dstlen;
	int srclen;
	unsigned char *ptr;
	int len;
	int err = 0;
	unsigned char menuver;
	memset(&dstaddr, 0, sizeof(struct sockaddr_dn));
	memset(&srcaddr, 0, sizeof(struct sockaddr_dn));
	cb->src_port = msg->srcaddr;
	cb->dst_port = msg->dstaddr;
	cb->services = msg->services;
	cb->info     = msg->info;
	cb->segsize  = dn_ntohs(msg->segsize);
	if (skb->len < sizeof(*msg))
		goto err_out;
	skb_pull(skb, sizeof(*msg));
	len = skb->len;
	ptr = skb->data;
	dstlen = dn_username2sockaddr(ptr, len, &dstaddr, &type);
	err++;
	if (dstlen < 0)
		goto err_out;
	err++;
	if (type > 1)
		goto err_out;
	len -= dstlen;
	ptr += dstlen;
	srclen = dn_username2sockaddr(ptr, len, &srcaddr, &type);
	err++;
	if (srclen < 0)
		goto err_out;
	len -= srclen;
	ptr += srclen;
	err++;
	if (len < 1)
		goto err_out;
	menuver = *ptr;
	ptr++;
	len--;
	err++;
	if ((menuver & (DN_MENUVER_ACC | DN_MENUVER_USR)) && (len < 1))
		goto err_out;
	err++;
	if (menuver & DN_MENUVER_ACC) {
		if (dn_check_idf(&ptr, &len, 39, 1))
			goto err_out;
		if (dn_check_idf(&ptr, &len, 39, 1))
			goto err_out;
		if (dn_check_idf(&ptr, &len, 39, (menuver & DN_MENUVER_USR) ? 1 : 0))
			goto err_out;
	}
	err++;
	if (menuver & DN_MENUVER_USR) {
		if (dn_check_idf(&ptr, &len, 16, 0))
			goto err_out;
	}
	return dn_sklist_find_listener(&dstaddr);
err_out:
	dn_log_martian(skb, ci_err_table[err].text);
	*reason = ci_err_table[err].reason;
	return NULL;
}
static struct sock * dn_find_listener ( struct sk_buff * skb , unsigned short * reason ) { struct dn_skb_cb * cb = ( struct dn_skb_cb * ) skb -> cb ; struct nsp_conn_init_msg * msg = ( struct nsp_conn_init_msg * ) skb -> data ; struct sockaddr_dn dstaddr ; struct sockaddr_dn srcaddr ; unsigned char type = 0 ; int dstlen ; int srclen ; unsigned char * ptr ; int len ; int err = 0 ; unsigned char menuver ; memset ( & dstaddr , 0 , sizeof ( struct sockaddr_dn ) ) ; memset ( & srcaddr , 0 , sizeof ( struct sockaddr_dn ) ) ; cb -> src_port = msg -> srcaddr ; cb -> dst_port = msg -> dstaddr ; cb -> services = msg -> services ; cb -> info = msg -> info ; cb -> segsize = dn_ntohs ( msg -> segsize ) ; if ( skb -> len < sizeof ( * msg ) ) goto err_out ; skb_pull ( skb , sizeof ( * msg ) ) ; len = skb -> len ; ptr = skb -> data ; dstlen = dn_username2sockaddr ( ptr , len , & dstaddr , & type ) ; err ++ ; if ( dstlen < 0 ) goto err_out ; err ++ ; if ( type > 1 ) goto err_out ; len -= dstlen ; ptr += dstlen ; srclen = dn_username2sockaddr ( ptr , len , & srcaddr , & type ) ; err ++ ; if ( srclen < 0 ) goto err_out ; len -= srclen ; ptr += srclen ; err ++ ; if ( len < 1 ) goto err_out ; menuver = * ptr ; ptr ++ ; len -- ; err ++ ; if ( ( menuver & ( DN_MENUVER_ACC | DN_MENUVER_USR ) ) && ( len < 1 ) ) goto err_out ; err ++ ; if ( menuver & DN_MENUVER_ACC ) { if ( dn_check_idf ( & ptr , & len , 39 , 1 ) ) goto err_out ; if ( dn_check_idf ( & ptr , & len , 39 , 1 ) ) goto err_out ; if ( dn_check_idf ( & ptr , & len , 39 , ( menuver & DN_MENUVER_USR ) ? 1 : 0 ) ) goto err_out ; } err ++ ; if ( menuver & DN_MENUVER_USR ) { if ( dn_check_idf ( & ptr , & len , 16 , 0 ) ) goto err_out ; } return dn_sklist_find_listener ( & dstaddr ) ; err_out : dn_log_martian ( skb , ci_err_table [ err ] . text ) ; * reason = ci_err_table [ err ] . reason ; return NULL ; }
This function uses a slightly different lookup method
 to find its sockets, since it searches on object name/number
 rather than port numbers.
This function uses a slightly different lookup method to find its sockets since it searches on object name / number rather than port numbers .
/*
	 * 1. Decode & remove message header
	 */ /*
	 * 2. Check destination end username format
	 */ /*
	 * 3. Check source end username format
	 */ /*
	 * 4. Check that optional data actually exists if menuver says it does
	 */ /*
	 * 5. Check optional access data format
	 */ /*
	 * 6. Check optional user data format
	 */ /*
	 * 7. Look up socket based on destination end username
	 */