📄 nmbd_packets.c
字号:
return send_netbios_packet( packet );} /*************************************************************************** Sends out a name release.**************************************************************************/static BOOL initiate_name_release_packet( struct packet_struct *packet, uint16 nb_flags, struct in_addr *release_ip){ struct nmb_packet *nmb = &packet->packet.nmb; nmb->header.opcode = NMB_NAME_RELEASE_OPCODE; nmb->header.arcount = 1; nmb->header.nm_flags.recursion_desired = False; if(create_and_init_additional_record(packet, nb_flags, release_ip) == False) return False; DEBUG(4,("initiate_name_release_packet: sending release for name %s (bcast=%s) to IP %s\n", nmb_namestr(&nmb->additional->rr_name), BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); return send_netbios_packet( packet );} /*************************************************************************** Sends out a node status.**************************************************************************/static BOOL initiate_node_status_packet( struct packet_struct *packet ){ struct nmb_packet *nmb = &packet->packet.nmb; nmb->header.opcode = NMB_NAME_QUERY_OPCODE; nmb->header.arcount = 0; nmb->header.nm_flags.recursion_desired = False; nmb->question.question_type = QUESTION_TYPE_NB_STATUS; DEBUG(4,("initiate_node_status_packet: sending node status request for name %s to IP %s\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(packet->ip))); return send_netbios_packet( packet );}/**************************************************************************** Simplification functions for queuing standard packets. These should be the only publicly callable functions for sending out packets.****************************************************************************//**************************************************************************** Assertion - we should never be sending nmbd packets on the remote broadcast subnet.****************************************************************************/static BOOL assert_check_subnet(struct subnet_record *subrec){ if( subrec == remote_broadcast_subnet) { DEBUG(0,("assert_check_subnet: Attempt to send packet on remote broadcast subnet. \This is a bug.\n")); return True; } return False;}/**************************************************************************** Queue a register name packet to the broadcast address of a subnet.****************************************************************************/struct response_record *queue_register_name( struct subnet_record *subrec, response_function resp_fn, timeout_response_function timeout_fn, register_name_success_function success_fn, register_name_fail_function fail_fn, struct userdata_struct *userdata, struct nmb_name *nmbname, uint16 nb_flags){ struct packet_struct *p; struct response_record *rrec; if(assert_check_subnet(subrec)) return NULL; /* note that all name registration requests have RD set (rfc1002 - section 4.2.2 */ if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), True, subrec->bcast_ip)) == NULL) return NULL; if(initiate_name_register_packet( p, nb_flags, iface_ip(subrec->bcast_ip)) == False) { p->locked = False; free_packet(p); return NULL; } if((rrec = make_response_record(subrec, /* subnet record. */ p, /* packet we sent. */ resp_fn, /* function to call on response. */ timeout_fn, /* function to call on timeout. */ (success_function)success_fn, /* function to call on operation success. */ (fail_function)fail_fn, /* function to call on operation fail. */ userdata)) == NULL) { p->locked = False; free_packet(p); return NULL; } return rrec;}/**************************************************************************** Queue a refresh name packet to the broadcast address of a subnet.****************************************************************************/void queue_wins_refresh(struct nmb_name *nmbname, response_function resp_fn, timeout_response_function timeout_fn, uint16 nb_flags, struct in_addr refresh_ip, const char *tag){ struct packet_struct *p; struct response_record *rrec; struct in_addr wins_ip; struct userdata_struct *userdata; fstring ip_str; wins_ip = wins_srv_ip_tag(tag, refresh_ip); if ((p = create_and_init_netbios_packet(nmbname, False, False, wins_ip)) == NULL) { return; } if (!initiate_name_refresh_packet(p, nb_flags, &refresh_ip)) { p->locked = False; free_packet(p); return; } fstrcpy(ip_str, inet_ntoa(refresh_ip)); DEBUG(6,("Refreshing name %s IP %s with WINS server %s using tag '%s'\n", nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag)); userdata = (struct userdata_struct *)SMB_MALLOC(sizeof(*userdata) + strlen(tag) + 1); if (!userdata) { DEBUG(0,("Failed to allocate userdata structure!\n")); return; } ZERO_STRUCTP(userdata); userdata->userdata_len = strlen(tag) + 1; strlcpy(userdata->data, tag, userdata->userdata_len); if ((rrec = make_response_record(unicast_subnet, p, resp_fn, timeout_fn, NULL, NULL, userdata)) == NULL) { p->locked = False; free_packet(p); return; } free(userdata); /* we don't want to repeat refresh packets */ rrec->repeat_count = 0;}/**************************************************************************** Queue a multihomed register name packet to a given WINS server IP****************************************************************************/struct response_record *queue_register_multihomed_name( struct subnet_record *subrec, response_function resp_fn, timeout_response_function timeout_fn, register_name_success_function success_fn, register_name_fail_function fail_fn, struct userdata_struct *userdata, struct nmb_name *nmbname, uint16 nb_flags, struct in_addr register_ip, struct in_addr wins_ip){ struct packet_struct *p; struct response_record *rrec; BOOL ret; /* Sanity check. */ if(subrec != unicast_subnet) { DEBUG(0,("queue_register_multihomed_name: should only be done on \unicast subnet. subnet is %s\n.", subrec->subnet_name )); return NULL; } if(assert_check_subnet(subrec)) return NULL; if ((p = create_and_init_netbios_packet(nmbname, False, True, wins_ip)) == NULL) return NULL; if (nb_flags & NB_GROUP) ret = initiate_name_register_packet( p, nb_flags, ®ister_ip); else ret = initiate_multihomed_name_register_packet(p, nb_flags, ®ister_ip); if (ret == False) { p->locked = False; free_packet(p); return NULL; } if ((rrec = make_response_record(subrec, /* subnet record. */ p, /* packet we sent. */ resp_fn, /* function to call on response. */ timeout_fn, /* function to call on timeout. */ (success_function)success_fn, /* function to call on operation success. */ (fail_function)fail_fn, /* function to call on operation fail. */ userdata)) == NULL) { p->locked = False; free_packet(p); return NULL; } return rrec;}/**************************************************************************** Queue a release name packet to the broadcast address of a subnet.****************************************************************************/struct response_record *queue_release_name( struct subnet_record *subrec, response_function resp_fn, timeout_response_function timeout_fn, release_name_success_function success_fn, release_name_fail_function fail_fn, struct userdata_struct *userdata, struct nmb_name *nmbname, uint16 nb_flags, struct in_addr release_ip, struct in_addr dest_ip){ struct packet_struct *p; struct response_record *rrec; if(assert_check_subnet(subrec)) return NULL; if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), False, dest_ip)) == NULL) return NULL; if(initiate_name_release_packet( p, nb_flags, &release_ip) == False) { p->locked = False; free_packet(p); return NULL; } if((rrec = make_response_record(subrec, /* subnet record. */ p, /* packet we sent. */ resp_fn, /* function to call on response. */ timeout_fn, /* function to call on timeout. */ (success_function)success_fn, /* function to call on operation success. */ (fail_function)fail_fn, /* function to call on operation fail. */ userdata)) == NULL) { p->locked = False; free_packet(p); return NULL; } /* * For a broadcast release packet, only send once. * This will cause us to remove the name asap. JRA. */ if (subrec != unicast_subnet) { rrec->repeat_count = 0; rrec->repeat_time = 0; } return rrec;}/**************************************************************************** Queue a query name packet to the broadcast address of a subnet.****************************************************************************/ struct response_record *queue_query_name( struct subnet_record *subrec, response_function resp_fn, timeout_response_function timeout_fn, query_name_success_function success_fn, query_name_fail_function fail_fn, struct userdata_struct *userdata, struct nmb_name *nmbname){ struct packet_struct *p; struct response_record *rrec; struct in_addr to_ip; if(assert_check_subnet(subrec)) return NULL; to_ip = subrec->bcast_ip; /* queries to the WINS server turn up here as queries to IP 0.0.0.0 These need to be handled a bit differently */ if (subrec->type == UNICAST_SUBNET && is_zero_ip(to_ip)) { /* What we really need to do is loop over each of our wins * servers and wins server tags here, but that just doesn't * fit our architecture at the moment (userdata may already * be used when we get here). For now we just query the first * active wins server on the first tag. */ char **tags = wins_srv_tags(); if (!tags) { return NULL; } to_ip = wins_srv_ip_tag(tags[0], to_ip); wins_srv_tags_free(tags); } if(( p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), (subrec == unicast_subnet), to_ip)) == NULL) return NULL; if(lp_bind_interfaces_only()) { int i; DEBUG(10,("queue_query_name: bind_interfaces_only is set, looking for suitable source IP\n")); for(i = 0; i < iface_count(); i++) { struct in_addr *ifip = iface_n_ip(i); if(ifip == NULL) { DEBUG(0,("queue_query_name: interface %d has NULL IP address !\n", i)); continue; } if (ip_equal(*ifip,loopback_ip)) { DEBUG(5,("queue_query_name: ignoring loopback interface (%d)\n", i)); continue; } DEBUG(10,("queue_query_name: using source IP %s\n",inet_ntoa(*ifip))); p->fd = find_subnet_fd_for_address( *ifip ); break; } } if(initiate_name_query_packet( p ) == False) { p->locked = False; free_packet(p); return NULL; } if((rrec = make_response_record(subrec, /* subnet record. */ p, /* packet we sent. */ resp_fn, /* function to call on response. */ timeout_fn, /* function to call on timeout. */ (success_function)success_fn, /* function to call on operation success. */ (fail_function)fail_fn, /* function to call on operation fail. */ userdata)) == NULL) { p->locked = False; free_packet(p); return NULL; } return rrec;}/**************************************************************************** Queue a query name packet to a given address from the WINS subnet.****************************************************************************/ struct response_record *queue_query_name_from_wins_server( struct in_addr to_ip, response_function resp_fn, timeout_response_function timeout_fn, query_name_success_function success_fn, query_name_fail_function fail_fn, struct userdata_struct *userdata,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -