📄 rpc_transport.c
字号:
smb_floor = (twr_empty_floor_t *)tower_data; tower_data += sizeof(*smb_floor); smb_floor->count_lhs = sizeof(smb_floor->protid); smb_floor->protid = EPM_PROTOCOL_SMB; smb_floor->count_rhs = endpoint_size; memcpy(tower_data, endpoint, endpoint_size); tower_data += endpoint_size; nb_floor = (twr_empty_floor_t *)tower_data; tower_data += sizeof(*nb_floor); nb_floor->count_lhs = sizeof(nb_floor->protid); nb_floor->protid = EPM_PROTOCOL_NETBIOS; nb_floor->count_rhs = networkaddr_size; memcpy(tower_data, networkaddr, networkaddr_size); tower_data += networkaddr_size; return size;}static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint){ const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data; const twr_empty_floor_t *nb_floor; TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); if (tower_size < sizeof(*smb_floor)) return EPT_S_NOT_REGISTERED; tower_data += sizeof(*smb_floor); tower_size -= sizeof(*smb_floor); if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) || (smb_floor->protid != EPM_PROTOCOL_SMB) || (smb_floor->count_rhs > tower_size)) return EPT_S_NOT_REGISTERED; if (endpoint) { *endpoint = I_RpcAllocate(smb_floor->count_rhs); if (!*endpoint) return RPC_S_OUT_OF_RESOURCES; memcpy(*endpoint, tower_data, smb_floor->count_rhs); } tower_data += smb_floor->count_rhs; tower_size -= smb_floor->count_rhs; if (tower_size < sizeof(*nb_floor)) return EPT_S_NOT_REGISTERED; nb_floor = (const twr_empty_floor_t *)tower_data; tower_data += sizeof(*nb_floor); tower_size -= sizeof(*nb_floor); if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) || (nb_floor->protid != EPM_PROTOCOL_NETBIOS) || (nb_floor->count_rhs > tower_size)) return EPT_S_NOT_REGISTERED; if (networkaddr) { *networkaddr = I_RpcAllocate(nb_floor->count_rhs); if (!*networkaddr) { if (endpoint) { I_RpcFree(*endpoint); *endpoint = NULL; } return RPC_S_OUT_OF_RESOURCES; } memcpy(*networkaddr, tower_data, nb_floor->count_rhs); } return RPC_S_OK;}typedef struct _RpcServerProtseq_np{ RpcServerProtseq common; HANDLE mgr_event;} RpcServerProtseq_np;static RpcServerProtseq *rpcrt4_protseq_np_alloc(void){ RpcServerProtseq_np *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps)); if (ps) ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL); return &ps->common;}static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq){ RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common); SetEvent(npps->mgr_event);}static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count){ HANDLE *objs = prev_array; RpcConnection_np *conn; RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common); EnterCriticalSection(&protseq->cs); /* open and count connections */ *count = 1; conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); while (conn) { rpcrt4_conn_listen_pipe(conn); if (conn->ovl.hEvent) (*count)++; conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); } /* make array of connections */ if (objs) objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE)); else objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE)); if (!objs) { ERR("couldn't allocate objs\n"); LeaveCriticalSection(&protseq->cs); return NULL; } objs[0] = npps->mgr_event; *count = 1; conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); while (conn) { if ((objs[*count] = conn->ovl.hEvent)) (*count)++; conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); } LeaveCriticalSection(&protseq->cs); return objs;}static void rpcrt4_protseq_np_free_wait_array(RpcServerProtseq *protseq, void *array){ HeapFree(GetProcessHeap(), 0, array);}static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array){ HANDLE b_handle; HANDLE *objs = wait_array; DWORD res; RpcConnection *cconn; RpcConnection_np *conn; if (!objs) return -1; res = WaitForMultipleObjects(count, objs, FALSE, INFINITE); if (res == WAIT_OBJECT_0) return 0; else if (res == WAIT_FAILED) { ERR("wait failed with error %d\n", GetLastError()); return -1; } else { b_handle = objs[res - WAIT_OBJECT_0]; /* find which connection got a RPC */ EnterCriticalSection(&protseq->cs); conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); while (conn) { if (b_handle == conn->ovl.hEvent) break; conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); } cconn = NULL; if (conn) RPCRT4_SpawnConnection(&cconn, &conn->common); else ERR("failed to locate connection for handle %p\n", b_handle); LeaveCriticalSection(&protseq->cs); if (cconn) { RPCRT4_new_client(cconn); return 1; } else return -1; }}static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data, const char *networkaddr, const char *endpoint){ twr_empty_floor_t *pipe_floor; size_t size; size_t endpoint_size; TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); endpoint_size = strlen(networkaddr) + 1; size = sizeof(*pipe_floor) + endpoint_size; if (!tower_data) return size; pipe_floor = (twr_empty_floor_t *)tower_data; tower_data += sizeof(*pipe_floor); pipe_floor->count_lhs = sizeof(pipe_floor->protid); pipe_floor->protid = EPM_PROTOCOL_SMB; pipe_floor->count_rhs = endpoint_size; memcpy(tower_data, endpoint, endpoint_size); tower_data += endpoint_size; return size;}static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint){ const twr_empty_floor_t *pipe_floor = (const twr_empty_floor_t *)tower_data; TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); *networkaddr = NULL; *endpoint = NULL; if (tower_size < sizeof(*pipe_floor)) return EPT_S_NOT_REGISTERED; tower_data += sizeof(*pipe_floor); tower_size -= sizeof(*pipe_floor); if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) || (pipe_floor->protid != EPM_PROTOCOL_SMB) || (pipe_floor->count_rhs > tower_size)) return EPT_S_NOT_REGISTERED; if (endpoint) { *endpoint = I_RpcAllocate(pipe_floor->count_rhs); if (!*endpoint) return RPC_S_OUT_OF_RESOURCES; memcpy(*endpoint, tower_data, pipe_floor->count_rhs); } return RPC_S_OK;}/**** ncacn_ip_tcp support ****/typedef struct _RpcConnection_tcp{ RpcConnection common; int sock;} RpcConnection_tcp;static RpcConnection *rpcrt4_conn_tcp_alloc(void){ RpcConnection_tcp *tcpc; tcpc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_tcp)); if (tcpc == NULL) return NULL; tcpc->sock = -1; return &tcpc->common;}static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection){ RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; int sock; int ret; struct addrinfo *ai; struct addrinfo *ai_cur; struct addrinfo hints; TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint); if (tcpc->sock != -1) return RPC_S_OK; hints.ai_flags = 0; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_addrlen = 0; hints.ai_addr = NULL; hints.ai_canonname = NULL; hints.ai_next = NULL; ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai); if (ret) { ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr, Connection->Endpoint, gai_strerror(ret)); return RPC_S_SERVER_UNAVAILABLE; } for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) { int val; if (TRACE_ON(rpc)) { char host[256]; char service[256]; getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV); TRACE("trying %s:%s\n", host, service); } sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); if (sock < 0) { WARN("socket() failed: %s\n", strerror(errno)); continue; } if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen)) { WARN("connect() failed: %s\n", strerror(errno)); close(sock); continue; } /* RPC depends on having minimal latency so disable the Nagle algorithm */ val = 1; setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); tcpc->sock = sock; freeaddrinfo(ai); TRACE("connected\n"); return RPC_S_OK; } freeaddrinfo(ai); ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint); return RPC_S_SERVER_UNAVAILABLE;}static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint){ RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT; int sock; int ret; struct addrinfo *ai; struct addrinfo *ai_cur; struct addrinfo hints; RpcConnection *first_connection = NULL; u_long blocking; TRACE("(%p, %s)\n", protseq, endpoint); hints.ai_flags = AI_PASSIVE /* for non-localhost addresses */; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_addrlen = 0; hints.ai_addr = NULL; hints.ai_canonname = NULL; hints.ai_next = NULL; ret = getaddrinfo(NULL, endpoint, &hints, &ai); if (ret) { ERR("getaddrinfo for port %s failed: %s\n", endpoint, gai_strerror(ret)); if ((ret == EAI_SERVICE) || (ret == EAI_NONAME)) return RPC_S_INVALID_ENDPOINT_FORMAT; return RPC_S_CANT_CREATE_ENDPOINT; } for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) { RpcConnection_tcp *tcpc; RPC_STATUS create_status; if (TRACE_ON(rpc)) { char host[256]; char service[256]; getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV); TRACE("trying %s:%s\n", host, service); } sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); if (sock < 0) { WARN("socket() failed: %s\n", strerror(errno)); status = RPC_S_CANT_CREATE_ENDPOINT; continue; } ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen); if (ret < 0) { WARN("bind failed: %s\n", strerror(errno)); close(sock); if (errno == WSAEADDRINUSE) status = RPC_S_DUPLICATE_ENDPOINT; else status = RPC_S_CANT_CREATE_ENDPOINT; continue; } create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE, protseq->Protseq, NULL, endpoint, NULL, NULL, NULL); if (create_status != RPC_S_OK) { close(sock); status = create_status; continue; } tcpc->sock = sock; ret = listen(sock, protseq->MaxCalls); if (ret < 0) { WARN("listen failed: %s\n", strerror(errno)); RPCRT4_DestroyConnection(&tcpc->common); status = RPC_S_OUT_OF_RESOURCES; continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -