]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/rfcnb/session.c
3 /* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
8 * Copyright (C) Richard Sharpe 1996
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 int RFCNB_saved_errno
= 0;
32 #include "rfcnb/std-includes.h"
33 #include <netinet/tcp.h>
34 #include "rfcnb/rfcnb.h"
35 #include "rfcnb/rfcnb-priv.h"
36 #include "rfcnb/rfcnb-io.h"
37 #include "rfcnb/rfcnb-util.h"
43 int RFCNB_Stats
[RFCNB_MAX_STATS
];
45 typedef void RFCNB_Prot_Print_Routine(FILE * fd
, int dir
, struct RFCNB_Pkt
*pkt
, int header
, int payload
);
46 RFCNB_Prot_Print_Routine
*Prot_Print_Routine
= NULL
; /* Pointer to protocol print routine */
48 int RFCNB_Get_Last_Errno(void);
49 int RFCNB_Get_Error_Msg(int code
, char *msg_buf
, int len
);
50 void RFCNB_Register_Print_Routine(RFCNB_Prot_Print_Routine
* fn
);
52 /* Set up a session with a remote name. We are passed Called_Name as a
53 * string which we convert to a NetBIOS name, ie space terminated, up to
54 * 16 characters only if we need to. If Called_Address is not empty, then
55 * we use it to connect to the remote end, but put in Called_Name ... Called
56 * Address can be a DNS based name, or a TCP/IP address ...
60 RFCNB_Call(char *Called_Name
, char *Calling_Name
, char *Called_Address
, int port
)
62 struct RFCNB_Con
*con
;
63 struct in_addr Dest_IP
;
66 struct redirect_addr
*redir_addr
;
67 char *Service_Address
;
69 /* Now, we really should look up the port in /etc/services ... */
72 port
= RFCNB_Default_Port
;
74 /* Create a connection structure first */
76 if ((con
= (struct RFCNB_Con
*) malloc(sizeof(struct RFCNB_Con
))) == NULL
) { /* Error in size */
78 RFCNB_errno
= RFCNBE_NoSpace
;
79 RFCNB_saved_errno
= errno
;
83 con
->fd
= -0; /* no descriptor yet */
84 con
->errn
= 0; /* no error yet */
85 con
->timeout
= 0; /* no timeout */
88 /* Resolve that name into an IP address */
90 Service_Address
= Called_Name
;
91 if (strcmp(Called_Address
, "") != 0) { /* If the Called Address = "" */
92 Service_Address
= Called_Address
;
94 if ((errno
= RFCNB_Name_To_IP(Service_Address
, &Dest_IP
)) < 0) { /* Error */
96 /* No need to modify RFCNB_errno as it was done by RFCNB_Name_To_IP */
101 /* Now connect to the remote end */
103 redirect
= TRUE
; /* Fudge this one so we go once through */
105 while (redirect
) { /* Connect and get session info etc */
107 redirect
= FALSE
; /* Assume all OK */
109 /* Build the redirect info. First one is first addr called */
110 /* And tack it onto the list of addresses we called */
112 if ((redir_addr
= (struct redirect_addr
*) malloc(sizeof(struct redirect_addr
))) == NULL
) { /* Could not get space */
114 RFCNB_errno
= RFCNBE_NoSpace
;
115 RFCNB_saved_errno
= errno
;
120 memcpy((char *) &(redir_addr
->ip_addr
), (char *) &Dest_IP
, sizeof(Dest_IP
));
121 redir_addr
->port
= port
;
122 redir_addr
->next
= NULL
;
124 if (con
->redirect_list
== NULL
) { /* Stick on head */
126 con
->redirect_list
= con
->last_addr
= redir_addr
;
130 con
->last_addr
->next
= redir_addr
;
131 con
->last_addr
= redir_addr
;
135 /* Now, make that connection */
137 if ((Client
= RFCNB_IP_Connect(Dest_IP
, port
)) < 0) { /* Error */
139 /* No need to modify RFCNB_errno as it was done by RFCNB_IP_Connect */
146 /* Now send and handle the RFCNB session request */
147 /* If we get a redirect, we will comeback with redirect true
148 * and a new IP address in DEST_IP */
150 if ((errno
= RFCNB_Session_Req(con
,
153 &redirect
, &Dest_IP
, &port
)) < 0) {
155 /* No need to modify RFCNB_errno as it was done by RFCNB_Session.. */
157 RFCNB_Close(con
->fd
); /* Close it */
164 /* We have to close the connection, and then try again */
168 RFCNB_Close(con
->fd
); /* Close it */
176 /* We send a packet to the other end ... for the moment, we treat the
177 * data as a series of pointers to blocks of data ... we should check the
180 RFCNB_Send(struct RFCNB_Con
*Con_Handle
, struct RFCNB_Pkt
*udata
, int Length
)
182 struct RFCNB_Pkt
*pkt
;
186 /* Plug in the header and send the data */
188 pkt
= RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len
);
192 RFCNB_errno
= RFCNBE_NoSpace
;
193 RFCNB_saved_errno
= errno
;
197 pkt
->next
= udata
; /* The user data we want to send */
201 /* Following crap is for portability across multiple UNIX machines */
203 *(hdr
+ RFCNB_Pkt_Type_Offset
) = RFCNB_SESSION_MESSAGE
;
204 RFCNB_Put_Pkt_Len(hdr
, Length
);
208 fprintf(stderr
, "Sending packet: ");
212 if ((len
= RFCNB_Put_Pkt(Con_Handle
, pkt
, Length
+ RFCNB_Pkt_Hdr_Len
)) < 0) {
214 /* No need to change RFCNB_errno as it was done by put_pkt ... */
216 return (RFCNBE_Bad
); /* Should be able to write that lot ... */
219 /* Now we have sent that lot, let's get rid of the RFCNB Header and return */
228 /* We pick up a message from the internet ... We have to worry about
229 * non-message packets ... */
231 RFCNB_Recv(void *con_Handle
, struct RFCNB_Pkt
*Data
, int Length
)
233 struct RFCNB_Pkt
*pkt
;
234 // struct RFCNB_Hdr *hdr;
237 if (con_Handle
== NULL
) {
239 RFCNB_errno
= RFCNBE_BadHandle
;
240 RFCNB_saved_errno
= errno
;
244 /* Now get a packet from below. We allocate a header first */
246 /* Plug in the header and send the data */
248 pkt
= RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len
);
252 RFCNB_errno
= RFCNBE_NoSpace
;
253 RFCNB_saved_errno
= errno
;
257 pkt
->next
= Data
; /* Plug in the data portion */
259 if ((ret_len
= RFCNB_Get_Pkt(con_Handle
, pkt
, Length
+ RFCNB_Pkt_Hdr_Len
)) < 0) {
262 fprintf(stderr
, "Bad packet return in RFCNB_Recv... \n");
268 /* We should check that we go a message and not a keep alive */
277 /* We just disconnect from the other end, as there is nothing in the RFCNB */
278 /* protocol that specifies any exchange as far as I can see */
280 RFCNB_Hangup(struct RFCNB_Con
*con_Handle
)
283 if (con_Handle
!= NULL
) {
284 RFCNB_Close(con_Handle
->fd
); /* Could this fail? */
290 /* Set TCP_NODELAY on the socket */
292 RFCNB_Set_Sock_NoDelay(struct RFCNB_Con
*con_Handle
, BOOL yn
)
295 return (setsockopt(con_Handle
->fd
, IPPROTO_TCP
, TCP_NODELAY
,
296 (char *) &yn
, sizeof(yn
)));
300 /* Listen for a connection on a port???, when */
301 /* the connection comes in, we return with the connection */
309 /* Pick up the last error response as a string, hmmm, this routine should */
310 /* have been different ... */
312 RFCNB_Get_Error(char *buffer
, int buf_len
)
315 if (RFCNB_saved_errno
<= 0) {
316 snprintf(buffer
, (buf_len
- 1), "%s", RFCNB_Error_Strings
[RFCNB_errno
]);
318 snprintf(buffer
, (buf_len
- 1), "%s\n\terrno:%s", RFCNB_Error_Strings
[RFCNB_errno
],
319 strerror(RFCNB_saved_errno
));
323 /* Pick up the last error response and returns as a code */
325 RFCNB_Get_Last_Error()
327 return (RFCNB_errno
);
330 /* Pick up saved errno as well */
332 RFCNB_Get_Last_Errno()
334 return (RFCNB_saved_errno
);
337 /* Pick up the last error response and return in string ... */
339 RFCNB_Get_Error_Msg(int code
, char *msg_buf
, int len
)
341 return (strncpy(msg_buf
, RFCNB_Error_Strings
[abs(code
)], len
) != NULL
);
344 /* Register a higher level protocol print routine */
346 RFCNB_Register_Print_Routine(RFCNB_Prot_Print_Routine
* fn
)
348 Prot_Print_Routine
= fn
;