📄 nmbd_packets.c
字号:
struct nmb_name *nmbname){ struct packet_struct *p; struct response_record *rrec; if ((p = create_and_init_netbios_packet(nmbname, False, False, to_ip)) == NULL) return NULL; if(initiate_name_query_packet_from_wins_server( p ) == False) { p->locked = False; free_packet(p); return NULL; } if((rrec = make_response_record(wins_server_subnet, /* 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 node status packet to a given name and address.****************************************************************************/ struct response_record *queue_node_status( struct subnet_record *subrec, response_function resp_fn, timeout_response_function timeout_fn, node_status_success_function success_fn, node_status_fail_function fail_fn, struct userdata_struct *userdata, struct nmb_name *nmbname, struct in_addr send_ip){ struct packet_struct *p; struct response_record *rrec; /* 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, False, send_ip)) == NULL) return NULL; if(initiate_node_status_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;}/**************************************************************************** Reply to a netbios name packet. see rfc1002.txt****************************************************************************/void reply_netbios_packet(struct packet_struct *orig_packet, int rcode, enum netbios_reply_type_code rcv_code, int opcode, int ttl, char *data,int len){ struct packet_struct packet; struct nmb_packet *nmb = NULL; struct res_rec answers; struct nmb_packet *orig_nmb = &orig_packet->packet.nmb; BOOL loopback_this_packet = False; int rr_type = RR_TYPE_NB; const char *packet_type = "unknown"; /* Check if we are sending to or from ourselves. */ if(ismyip(orig_packet->ip) && (orig_packet->port == global_nmb_port)) loopback_this_packet = True; nmb = &packet.packet.nmb; /* Do a partial copy of the packet. We clear the locked flag and the resource record pointers. */ packet = *orig_packet; /* Full structure copy. */ packet.locked = False; nmb->answers = NULL; nmb->nsrecs = NULL; nmb->additional = NULL; switch (rcv_code) { case NMB_STATUS: packet_type = "nmb_status"; nmb->header.nm_flags.recursion_desired = False; nmb->header.nm_flags.recursion_available = False; rr_type = RR_TYPE_NBSTAT; break; case NMB_QUERY: packet_type = "nmb_query"; nmb->header.nm_flags.recursion_desired = True; nmb->header.nm_flags.recursion_available = True; if (rcode) { rr_type = RR_TYPE_NULL; } break; case NMB_REG: case NMB_REG_REFRESH: packet_type = "nmb_reg"; nmb->header.nm_flags.recursion_desired = True; nmb->header.nm_flags.recursion_available = True; break; case NMB_REL: packet_type = "nmb_rel"; nmb->header.nm_flags.recursion_desired = False; nmb->header.nm_flags.recursion_available = False; break; case NMB_WAIT_ACK: packet_type = "nmb_wack"; nmb->header.nm_flags.recursion_desired = False; nmb->header.nm_flags.recursion_available = False; rr_type = RR_TYPE_NULL; break; case WINS_REG: packet_type = "wins_reg"; nmb->header.nm_flags.recursion_desired = True; nmb->header.nm_flags.recursion_available = True; break; case WINS_QUERY: packet_type = "wins_query"; nmb->header.nm_flags.recursion_desired = True; nmb->header.nm_flags.recursion_available = True; if (rcode) { rr_type = RR_TYPE_NULL; } break; default: DEBUG(0,("reply_netbios_packet: Unknown packet type: %s %s to ip %s\n", packet_type, nmb_namestr(&orig_nmb->question.question_name), inet_ntoa(packet.ip))); return; } DEBUG(4,("reply_netbios_packet: sending a reply of packet type: %s %s to ip %s \for id %hu\n", packet_type, nmb_namestr(&orig_nmb->question.question_name), inet_ntoa(packet.ip), orig_nmb->header.name_trn_id)); nmb->header.name_trn_id = orig_nmb->header.name_trn_id; nmb->header.opcode = opcode; nmb->header.response = True; nmb->header.nm_flags.bcast = False; nmb->header.nm_flags.trunc = False; nmb->header.nm_flags.authoritative = True; nmb->header.rcode = rcode; nmb->header.qdcount = 0; nmb->header.ancount = 1; nmb->header.nscount = 0; nmb->header.arcount = 0; memset((char*)&nmb->question,'\0',sizeof(nmb->question)); nmb->answers = &answers; memset((char*)nmb->answers,'\0',sizeof(*nmb->answers)); nmb->answers->rr_name = orig_nmb->question.question_name; nmb->answers->rr_type = rr_type; nmb->answers->rr_class = RR_CLASS_IN; nmb->answers->ttl = ttl; if (data && len) { nmb->answers->rdlength = len; memcpy(nmb->answers->rdata, data, len); } packet.packet_type = NMB_PACKET; /* Ensure we send out on the same fd that the original packet came in on to give the correct source IP address. */ packet.fd = orig_packet->fd; packet.timestamp = time(NULL); debug_nmb_packet(&packet); if(loopback_this_packet) { struct packet_struct *lo_packet; DEBUG(5,("reply_netbios_packet: sending packet to ourselves.\n")); if((lo_packet = copy_packet(&packet)) == NULL) return; queue_packet(lo_packet); } else if (!send_packet(&packet)) { DEBUG(0,("reply_netbios_packet: send_packet to IP %s port %d failed\n", inet_ntoa(packet.ip),packet.port)); }}/******************************************************************* Queue a packet into a packet queue******************************************************************/static void queue_packet(struct packet_struct *packet){ struct packet_struct *p; if (!packet_queue) { packet->prev = NULL; packet->next = NULL; packet_queue = packet; return; } /* find the bottom */ for (p=packet_queue;p->next;p=p->next) ; p->next = packet; packet->next = NULL; packet->prev = p;}/**************************************************************************** Try and find a matching subnet record for a datagram port 138 packet.****************************************************************************/static struct subnet_record *find_subnet_for_dgram_browse_packet(struct packet_struct *p){ struct subnet_record *subrec; /* Go through all the broadcast subnets and see if the mask matches. */ for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) return subrec; } /* If the subnet record is the remote announce broadcast subnet, hack it here to be the first subnet. This is really gross and is needed due to people turning on port 137/138 broadcast forwarding on their routers. May fire and brimstone rain down upon them... */ return FIRST_SUBNET;}/****************************************************************************Dispatch a browse frame from port 138 to the correct processing function.****************************************************************************/static void process_browse_packet(struct packet_struct *p, char *buf,int len){ struct dgram_packet *dgram = &p->packet.dgram; int command = CVAL(buf,0); struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p); char scope[64]; unstring src_name; /* Drop the packet if it's a different NetBIOS scope, or the source is from one of our names. */ pull_ascii(scope, dgram->dest_name.scope, 64, 64, STR_TERMINATE); if (!strequal(scope, global_scope())) { DEBUG(7,("process_browse_packet: Discarding datagram from IP %s. Scope (%s) \mismatch with our scope (%s).\n", inet_ntoa(p->ip), scope, global_scope())); return; } pull_ascii_nstring(src_name, sizeof(src_name), dgram->source_name.name); if (is_myname(src_name)) { DEBUG(0,("process_browse_packet: Discarding datagram from IP %s. Source name \%s is one of our names !\n", inet_ntoa(p->ip), nmb_namestr(&dgram->source_name))); return; } switch (command) { case ANN_HostAnnouncement: debug_browse_data(buf, len); process_host_announce(subrec, p, buf+1); break; case ANN_DomainAnnouncement: debug_browse_data(buf, len); process_workgroup_announce(subrec, p, buf+1); break; case ANN_LocalMasterAnnouncement: debug_browse_data(buf, len); process_local_master_announce(subrec, p, buf+1); break; case ANN_AnnouncementRequest: debug_browse_data(buf, len); process_announce_request(subrec, p, buf+1); break; case ANN_Election: debug_browse_data(buf, len); process_election(subrec, p, buf+1); break; case ANN_GetBackupListReq: debug_browse_data(buf, len); process_get_backup_list_request(subrec, p, buf+1); break; case ANN_GetBackupListResp: debug_browse_data(buf, len); /* We never send ANN_GetBackupListReq so we should never get these. */ DEBUG(0,("process_browse_packet: Discarding GetBackupListResponse \packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip))); break; case ANN_ResetBrowserState: debug_browse_data(buf, len); process_reset_browser(subrec, p, buf+1); break; case ANN_MasterAnnouncement: /* Master browser datagrams must be processed on the unicast subnet. */ subrec = unicast_subnet; debug_browse_data(buf, len); process_master_browser_announce(subrec, p, buf+1); break; case ANN_BecomeBackup: /* * We don't currently implement this. Log it just in case. */ debug_browse_data(buf, len); DEBUG(10,("process_browse_packet: On subnet %s ignoring browse packet \command ANN_BecomeBackup from %s IP %s to %s\n", subrec->subnet_name, nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); break; default: debug_browse_data(buf, len); DEBUG(0,("process_browse_packet: On subnet %s ignoring browse packet \command code %d from %s IP %s to %s\n", subrec->subnet_name, command, nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); break; } }/**************************************************************************** Dispatch a LanMan browse frame from port 138 to the correct processing function.****************************************************************************/static void process_lanman_packet(struct packet_struct *p, char *buf,int len){ struct dgram_packet *dgram = &p->packet.dgram; int command = SVAL(buf,0); struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p); char scope[64]; unstring src_name; /* Drop the packet if it's a different NetBIOS scope, or the source is from one of our names. */ pull_ascii(scope, dgram->dest_name.scope, 64, 64, STR_TERMINATE); if (!strequal(scope, global_scope())) { DEBUG(7,("process_lanman_packet: Discarding datagram from IP %s. Scope (%s) \mismatch with our scope (%s).\n", inet_ntoa(p->ip), scope, global_scope())); return; } pull_ascii_nstring(src_name, sizeof(src_name), dgram->source_name.name); if (is_myname(src_name)) { DEBUG(0,("process_lanman_packet: Discarding datagram from IP %s. Source name \%s is one of our names !\n", inet_ntoa(p->ip), nmb_namestr(&dgram->source_name))); return; } switch (command) { case ANN_HostAnnouncement: debug_browse_data(buf, len); process_lm_host_announce(subrec, p, buf+1); break; case ANN_AnnouncementRequest: process_lm_announce_request(subrec, p, buf+1); break; default: DEBUG(0,("process_lanman_packet: On subnet %s ignoring browse packet \command code %d from %s IP %s to %s\n", subrec->subnet_name, command, nmb_namestr(&dgram->source_name),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -