Par le terme 'Raw' c'est la gestion du 'terminal' dont à laquelle je faisais allusion ce que tu soulignes de manières plus détaillée et précise.
Version imprimable
C'est Normal, il y a des posts dans lesquels on peut s'enliser ce n'est pas pour autant qu'il faut se décourager... même si l'objet dans le fil ... peut paraître absurde parfois la finalité est surprenante ;)
(PS : j'ai travaillé sur "l'histoire" du backspace il y a dix ans celà m'avait pas mal refroidit !)
@dva2tlse ->
La tendance étant à l'économie d'énergie :
Regarde le code source de PuTTY qui est opensource gère fonctionnalités Telnet, SSH et en + Autologin et + encore.
Tu comprendras que tout celà n'est pas que l'initialisation d'une chaussette :D
Ok merci les gars, ça me fait du boulot pour ce ouikennedeu, de tout assimiler et le transcrire dans mon code; je ne réponds pas point par point à tout ce que vous me donnez comme infos, mais après une simple première lecture je retiens ce qu'a dit delete :OUI, je suis un gros nâze et je veux le faire moi même: NA (smiley qui tape du pied), et c'est pour ça que ceci ne me plait pas :Citation:
Peut être en satisfaction personnelle ... ?
ni des bibliothèques ou autres applications déjà faites, ou toutes prêtes, ou sur étagère.Code:telnet <monip>
à une prochaine fois quand j'aurai un peu avancé, parce que je suppose bien que j'aurai encore besoin de votre aide,
encore merci,
David
Bon, alors comme prévu hier, j'ai besoin d'aide : (mais je ne tire aucune fierté de cette très facile prédiction)
J'ai super-bien nettoyé mon code par rapport au fouillis précédent, à tel point que j'estime pouvoir le donner plus bas; mais il reste un problème au moment de l'établissement final de la session telnet.
Il se connecte bien a mon FAI qu'il trouve par gethostbyname(), puis je fais un ECHO_REQUEST en lui envoyant un paquet que j'ai savamment forgé (smiley fier) puis je lis ma propre IP dans le paquet qu'il me renvoit.
J'utilise cette IP pour me connecter avec succés à mon propre serveur telnet, mais pour initier la session ça se passe mal pour le login et password puisqu'il me fait les choses suivantes :
Voici mon code :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 david@test:~/Skul1-telnet$ gcc mtn.c -o mtn david@test:~/Skul1-telnet$ sudo ./mtn wanadoo.fr monip: Ok pour le premier socket qui sert au ping. monip: h->h_name=wanadoo.fr (résolu par gethostbyname sur ce socket) imppkt: Ok impression du paquet envoyé : imppkt: type=8, code=0, chksum=65527 monip: adresse dest.=1736113345 monip: long2ip(1736113345) => 103.122.252.193 monip: host de dest.=wanadoo.fr (le même h->h_name que résolu ci dessus) monip: avant recvfrom monip: Ok après recvfrom monip: wanadoo.fr is alive ! imppkt: Ok impression du paquet reçu : imppkt: type=0, code=0, chksum=65535 monip: adresse source=1736113345 long2ip(1736113345) => 103.122.252.193 monip: host de source du retour=hpwoo.wanadooportails.com (hh->h_name) monip: gethostbyaddr() Ok monip: adresse src du retour=103.122.252.193 monip: adresse dst du retour=aaa.bbb.cc.dd mtn: monIP=aaa.bbb.cc.dd mtn: ici Stn: là, monIP=aaa.bbb.cc.dd (=eeeee en %u) Stn: Contrôles : Stn: sin.sin_port=23 Stn: sin.sin_family=2 Stn: sin.sin_addr.s_addr=eeeee, (=aaa.bbb.cc.dd) Stn: connect() Ok Stn: try to log in, now : (CRLF=" " Stn: invite de login : ���� � Stn: envoi de guest+"CRLF" Stn: invite de password : noresp: No response from hpwoo.wanadooportails.com david@test:~/Skul1-telnet$
La fonction monip construit le ping et reçoit le pong pour en déduire ma propre IP; puis la fonction stn essaie d'établir une session telnet sur la machine dont il a reçu l'adresse. (et qui se trouve être la mienne, où j'ai un serveur telnet qui attend de la visite)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467 // Ceci est un essai pour comprendre ce qui se passe avec le net; mtn est un renvoi après le ping. // je veux que ce programme fasse du telnet chez moi; mtn=mon telnet. // gcc mtn.c -o mtn // "./mtn host" pour résolver l'host et avoir mon IP. // sudo ./mtn wanadoo.fr // // rappels sur les pointeurs : // &truc est l'adresse de truc // ptruc = &truc, l'adresse en question. // ptruc prend la même place qu'un entier, quel que soit le type de l'objet sur lequel il pointe. // int *ptruc; // ici, il pointera sur un entier. // int n=10; // n est un entier initialisé à 10. // ptruc=&n; // ptruc pointe sur n auquel on assède par *ptruc // *ptruc+=5; // l'objet sur lequel pointe ptruc est augémenté de cinq. // à partir d'ici, n vaut quinze. // // #include <arpa/inet.h> #include "client_telnet.h" #include <errno.h> #include <netdb.h> // déjà inclus dans client_telnet.h trois lignes plus haut : #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> // définit ICMP_ECHO et ICMP_ECHOREPLY. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/file.h> #include <sys/param.h> #include <sys/signal.h> #include <sys/socket.h> #include <sys/time.h> #include <sys/times.h> // // // It turns out that libc5 doesn't have proper icmp support // built into it header files, so we have to supplement it #if! defined __GLIBC__ && ! defined __UCLIBC__ typedef unsigned int socklen_t; // // ceci est une sous-structure de celle qui décrit le paquet icmp : struct icmp_ra_addr // ça, ça pourrait sûrement être les quatrième et cinquième mots { u_int32_t ira_addr; u_int32_t ira_preference; }; // // ceci est la structure du paquet icmp : struct icmp // TYPE, CODE, et CHECKSUM forment le sixième mot d'en-tête; // TTL les 16 1°-bits du 3-ième. { // 8 bits du sixième mot de quatre octets; 8=demande une réponse u_int8_t icmp_type; // type of message, see below 0=ICMP_ECHO, 8=ICMP_ECHOREPLY // (icmp_code=0 pour les deux) // et ça vaut 11/0 si la durée de vie est écoulée avant d'arriver // à destination. 8 bits suivants du sixième mot de quatre octets; // donc deuxième octet u_int8_t icmp_code; // type sub code // 16 bits suivants du sixième mot de quatre octets; // donc trois et quatrième octets u_int16_t icmp_cksum; // ones complement checksum of struct union { u_char ih_pptr; // ICMP_PARAMPROB struct in_addr ih_gwaddr; // gateway address struct ih_idseq // echo datagram { u_int16_t icd_id; u_int16_t icd_seq; } ih_idseq; u_int32_t ih_void; // ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) struct ih_pmtu { u_int16_t ipm_void; u_int16_t ipm_nextmtu; } ih_pmtu; struct ih_rtradv { u_int8_t irt_num_addrs; u_int8_t irt_wpa; u_int16_t irt_lifetime; } ih_rtradv; } icmp_hun; #define icmp_pptr icmp_hun.ih_pptr #define icmp_gwaddr icmp_hun.ih_gwaddr #define icmp_id icmp_hun.ih_idseq.icd_id #define icmp_seq icmp_hun.ih_idseq.icd_seq #define icmp_void icmp_hun.ih_void #define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void #define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu #define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs #define icmp_wpa icmp_hun.ih_rtradv.irt_wpa #define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime union { struct { u_int32_t its_otime; u_int32_t its_rtime; u_int32_t its_ttime; } id_ts; struct { struct ip idi_ip; // options and then 64 bits of data } id_ip; struct icmp_ra_addr id_radv; u_int32_t id_mask; u_int8_t id_data[1]; } icmp_dun; // fin de l'union #define icmp_otime icmp_dun.id_ts.its_otime #define icmp_rtime icmp_dun.id_ts.its_rtime #define icmp_ttime icmp_dun.id_ts.its_ttime #define icmp_ip icmp_dun.id_ip.idi_ip #define icmp_radv icmp_dun.id_radv #define icmp_mask icmp_dun.id_mask #define icmp_data icmp_dun.id_data }; // fin de la struct icmp; donc une struct icmp_ra_addr en fait partie, et elle est bien définie // avant, donc .ira_addr qui a un terme .ira_preference // devraient être accessibles avec icmp.id_radv.ira_preference... // #endif // fin du #if! defined __GLIBC__ && ! defined __UCLIBC__ // // #define DEFDATALEN 56 #define MAXIPLEN 60 #define MAXICMPLEN 76 #define MAXPACKET 65468 #define MAX_DUP_CHK (8 * 128) #define MAXWAIT 10 #define PINGINTERVAL 1 // second // #define O_QUIET (1 << 0) // #define A(bit) rcvd_tbl[(bit)>>3] // identify byte in array #define B(bit) (1 << ((bit) & 0x07)) // identify bit in byte #define SET(bit) (A(bit) |= B(bit)) #define CLR(bit) (A(bit) &= (~B(bit))) #define TST(bit) (A(bit) & B(bit)) // // #define LIN_SIZE 80 // // char *pmonIP; char *paddrIP; // // // Send ICMP ECHO_REQUEST packets to network hosts ///////////////////////////// static void ping(const char *host); //////////////////////////////////////////// // // static char *hostname = NULL; // préalable rassurant. // // static int in_cksum(unsigned short *buf, int sz) /////////////////////////////// { int nleft = sz; int sum = 0; unsigned short *w = buf; unsigned short ans = 0; // while (nleft > 1) { sum += *w++; nleft -= 2; } // if(nleft == 1) { *(unsigned char *) (&ans) = *(unsigned char *) w; sum += ans; } // sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); ans = ~sum; return(ans); } // // static int imppkt(struct icmp pkt, char *sens) ///////////////////////////////// { printf("\nimppkt: Ok impression du paquet %s :\n",sens); printf("imppkt: type=%u, code=%u, chksum=%u\n",pkt.icmp_type,pkt.icmp_code,pkt.icmp_cksum); return(0); } // // unsigned int ip2long(char *s) ////////////////////////////////////////////////// { struct sockaddr_in n; inet_aton(s,&n.sin_addr); return ntohl(n.sin_addr.s_addr); } // // char* long2ip(unsigned int v) ////////////////////////////////////////////////// { struct in_addr x; x.s_addr = htonl(v); // passe dans l' ordre reseau return inet_ntoa(x); // et convertit } // // static void noresp(int ign) //////////////////////////////////////////////////// { printf("noresp: No response from %s\n", hostname); exit(0); } // // static void read_server(SOCKET sock, char *buffer) { char *p; int n = 0; if((n = recv(sock, buffer, BUF_SIZE - 1, 0)) < 0) { perror("recv()"); exit(errno); } if(n == 0) { printf("read_server: Connection lost\n"); exit(EXIT_FAILURE); } buffer[n] = 0; p = strstr(buffer, CRLF); if(p != NULL) { *p = 0; } } // // static void write_server(SOCKET sock, char *buffer) { if(send(sock, buffer, strlen(buffer), 0) < 0) { perror("send()"); exit(errno); } } // // extern char* monip(int argc, const char *host) //////////////////////////////////////// { struct hostent *h, *hh; // h et hh pointent sur des structures hostent. // h est celle obtenue avant le ping-aller par gethostbyname(mon isp) // hh est celle obtenue avant le pong-retour par gethostbyaddr(sonIP) struct icmp *pkt; // pkt pointe sur une structure icmp. struct sockaddr_in pingaddr, sin; extern char *pmonIP; unsigned long addr; // le paquet a été envoyé là bas int c, pingsock, type; char buffer[16]; char command[BUF_SIZE]; char line[LIN_SIZE]; char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; // packet est un tableau de caractères. socklen_t len; // SOCKADDR_IN sin; // déjà défini qq lignes + haut SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); // if(argc<2 || strcmp(host,"-h")==0) { printf("\nmonip: Ce programme doit résolver [host],\n"); printf("monip: puis y envoyer un echorequest,\n"); printf("monip: puis en contrôler la teneur et la destination,\n"); printf("monip: puis contrôler la teneur et la provenance du retour.\n\n"); printf("monip: Ex: sudo ./mtn wanadoo.fr\n\n"); exit(1); } // if((pingsock = socket(AF_INET, SOCK_RAW, 1)) < 0) { // 1 == ICMP perror("monip: creating a raw socket"); exit(1); } else printf("\nmonip: Ok pour le premier socket qui sert au ping.\n"); // // drop root privs ifrunning setuid setuid(getuid()); // memset(&pingaddr, 0, sizeof(struct sockaddr_in)); // memset() remplit les n premiers octets // (avec n=sizeof(struct sockaddr_in)) de la zone mémoire pointée par s (s=&pingaddr) // avec loctet c (c=0). pingaddr.sin_family = AF_INET; // pingaddr est la struct sockaddr_in pour laquelle // vient d'être allouée de la mem. if(!(h = gethostbyname(host))) { fprintf(stderr, "monip: unknown host %s\n", host); exit(1); } memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr)); // memcpy() copie n octets // (n= sizeof(pingaddr.sin_addr)) depuis la zone mémoire src (src=h->h_addr) vers // la zone mémoire dest (dest=&pingaddr.sin_addr); ce qui veut dire qu'on prend le membre // h_addr de la struct hostent nommée h (qui vient d'être résolue par gethostbyname) pour // le placer à &pingaddr.sin_addr. hostname = h->h_name; printf("monip: h->h_name=%s (résolu par gethostbyname sur ce socket)\n",hostname); // pkt = (struct icmp *) packet; // rappel, pkt pointe sur une structure icmp; // ici elle s'appelle packet. memset(pkt, 0, sizeof(packet)); pkt->icmp_type = ICMP_ECHO; // le membre icmp_type de la struct icmp // pointée par pkt est rempli par ICMP_ECHO pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet)); // le cksum est // rempli aussi. // c = sendto(pingsock, packet, sizeof(packet), 0, (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in)); // ssize_t sendto(int s, const void *buf, size_t len, int flags, // const struct sockaddr *to, socklen_t tolen); if(c < 0 || c != sizeof(packet)) { if(c < 0) perror("monip: sendto"); fprintf(stderr, "monip: write incomplete\n"); exit(1); } else { // alors par ici je peux essayer d'imprimer le paquet envoyé : if(imppkt(*pkt, "envoyé")==-1) { printf("monip: Problème d'impression du paquet.\n"); } else { addr=(unsigned int)pingaddr.sin_addr.s_addr; // le paquet a été envoyé là-bas. printf("monip: adresse dest.=%u\n", addr); // je la veux en IP pointée. // // long2ip printf("monip: long2ip(%u) => %s\n", addr, long2ip(addr) ); // if(!(h = gethostbyname(host))) { fprintf(stderr, "monip: unknown host %s\n", host); exit(1); } else { printf("monip: host de dest.=%s (le même h->h_name que résolu ci dessus)\n\n", h->h_name); } } } // signal(SIGALRM, noresp); alarm(5); // give the host 5000ms to respond // listen for replies while (1) { struct sockaddr_in from; size_t fromlen = sizeof(from); // //ssize_t recvfrom(int s, void *buf, size_t len, int flags, // struct sockaddr *from, socklen_t *fromlen); printf( "monip: avant recvfrom\n"); if((c = recvfrom(pingsock, packet, sizeof(packet), 0, (struct sockaddr *) &from, &fromlen)) < 0) { if(errno == EINTR) continue; perror("monip: recvfrom"); continue; } // close(pingsock); // je n'ai plus besoin de ça. printf( "monip: Ok après recvfrom\n"); // if(c >= 76) { // ip + icmp struct iphdr *iphdr = (struct iphdr *) packet; // pkt = (struct icmp *) (packet + (iphdr->ihl << 2)); // skip ip hdr if(pkt->icmp_type == ICMP_ECHOREPLY) { printf("monip: %s is alive !\n", hostname); if(imppkt(*pkt, "reçu")==-1) { printf("monip: Problème d'impression du paquet.\n"); } else { // l'impression du paquet revenu est Ok addr=from.sin_addr.s_addr; // from est une struct sockaddr_in, // dont un membre nommé sin_addr est une struct in_addr, // dont le seul membre est s_addr. printf("monip: adresse source=%u\n", addr); // // long2ip printf( "long2ip(%u) => %s\n", addr, long2ip(addr) ); // // pour l'instant, AF_INET qui est le type vaut 2 if((hh=gethostbyaddr(&addr, sizeof(addr), 2))==NULL) { // struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type); perror("monip: gethostbyaddr()"); printf("monip: gethostbyaddr() pas Ok\n\n"); } else { // gethostbyaddr a créé une struct hostent qui s'appeller hh hostname = hh->h_name; printf("monip: host de source du retour=%s (hh->h_name)\n", hostname); printf("monip: gethostbyaddr() Ok\n\n"); printf("monip: adresse src du retour=%s\n", long2ip(iphdr->saddr)); // IP pointée. printf("monip: adresse dst du retour=%s\n\n", long2ip(iphdr->daddr)); // IP pntée. // pmonIP=long2ip(iphdr->daddr); // } // c'est donc ici la fin du else } break; } // } // } return pmonIP; // } // // static int Stn(char* paddrIP) { printf("Stn: là, monIP=%s (=%u en %%u)\n\n",paddrIP,ip2long(paddrIP)); SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); char command[BUF_SIZE]; char line[LIN_SIZE]; struct sockaddr_in sin; // creation d'un socket avec l'adresse que je construis ici : // pour l'instant il faut ma propre sin_addr; c'est une struct in_addr, sin.sin_addr.s_addr = ip2long(paddrIP); // dont le seul membre est s_addr... // // (de type in_addr_t) sin.sin_port = htons(PORT); // PORT=23 pour telnet. sin.sin_family = AF_INET; // pour l'instant, AF_INET qui est le type vaut 2 printf("Stn: Contrôles :\n"); // printf("Stn: sin.sin_addr=%u\n",sin.sin_addr); // c'est une sin_addr mais il affiche son membre printf("Stn: sin.sin_port=%d\n",ntohs(sin.sin_port)); // s_addr en unsigned printf("Stn: sin.sin_family=%d\n",AF_INET); printf("Stn: sin.sin_addr.s_addr=%u, (=%s)\n",sin.sin_addr.s_addr, // cela doit être long ds l'ordre n. long2ip(sin.sin_addr.s_addr)); if(connect(sock,(SOCKADDR *) &sin, sizeof(SOCKADDR)) == SOCKET_ERROR) { perror("Stn: connect()"); exit(errno); } else printf("Stn: connect() Ok\n\n"); printf("Stn: try to log in, now : (CRLF=\"%s\"\n",CRLF); // printf("Stn: invite de login :\n"); read_server(sock, line); // lecture de l'invite de login puts(line); // affichage de celle ci printf("Stn: envoi de %s+\"%s\"\n\n", "guest", "CRLF"); sprintf(command, "%s%s", "guest", CRLF); write_server(sock, command); // printf("Stn: invite de password :\n"); read_server(sock, line); // lecture de l'invite de password puts(line); // affichage de celle ci printf("Stn: envoi de %s+\"%s\"\n", "guest1", "CRLF"); sprintf(command, "%s%s", "guest1", CRLF); write_server(sock, command); // read_server(sock, line); puts(line); // printf("Stn: end of trial.\n"); // on n'arrive pas encore ici, tu rêves ??? return 0; } // // extern int main(int argc, char **argv) ///////////////////////////////////////// { //DVA: argc--; argv++; extern char* paddrIP; paddrIP=monip(argc, *argv); //////////////////////////////////////////////// printf("mtn: monIP=%s\n",paddrIP); printf("mtn: ici\n\n"); int a=Stn(paddrIP); //////////////////////////////////////////////////////// exit(1); } // // fin.
Il se trouve qu'au moment de lire les invites de login et password, et d'écrire ceux ci, mon PC ne se comprend plus lui même.
Mais je ne sais pas si la fonction fonction read_server a bien le bon type de socket à sa disposition pour me donner un résultat.
Mon serveur telnet est bel et bien à l'écoute comme le dit nmap :Merci de me donner encore quelques tuyaux pour attrapper ce telnet.Code:
1
2
3
4
5
6
7
8
9 david@test:~/Snet6-nmap$ nmap 127.0.0.1 -p 23 Starting Nmap 4.68 ( http://nmap.org ) at 2008-08-30 13:53 CEST Interesting ports on localhost (127.0.0.1): PORT STATE SERVICE 23/tcp open telnet Nmap done: 1 IP address (1 host up) scanned in 0.078 seconds david@test:~/Snet6-nmap$
David
Pour le ping, j'ai pas compris, mais c'est ta limonade interne :)
C'est bien naïf de ta part, de penser que tu peux te logger comme ça. 8O
Comme nous le disions avec Emmanuel Delahaye il faut utiliser une librairie, qui identifiera ton terminal et permettra de gérer le TTY selon ses contraintes et celles imposées par l'OS.
Sur la partie login, telnet renvoie l'echo, sur la partie password, ce n'est pas le cas. Un petit tours de RFC te ferait du bien (déjà citées)
Un fputs ne te servira à rien. Tu ne pourras jamais te logger.
Utilise au moins la lib Curl -> http://curl.haxx.se/
Qui te facilitera grandement la tache.
merci; je viens d'aller faire un tour dur le site en question mais je n'ai pas vu immédiatement en quoi ça pouvait me servir; mais j'y retourne...
[.../...]
...ce qui a été une bonne idée car ceci me plait bien :
merci du tuyau...Code:
1
2
3
4
5 TELNET - connection negotiation - custom telnet options - stdin/stdout I/O
[.../...]
...cependant l'information suivante me fait un peu peur :
Donc je vais être obligé de rechercher caractère par caractère quand il me demande ces infos; mais pouvez vous me dire si la façon de dialoguer avec le serveur que j'ai établie semble correcte ?Citation:
NOTE: the telnet protocol does not specify any way to login with a specified
user and password so curl can't do that automatically. To do that, you need
to track when the login prompt is received and send the username and
password accordingly.
Je vais essayer de voir avec tcpdump ce que mon serveur et son client se disent...
à +,
David
PS pour delete,oui;il est juste un peu dommage que le fait que tu n'aies rien compris signifie soit que j'ai très mal explqué, soit que j'ai fait des choses vraiment pas claires; enfin bon...Citation:
c'est ta limonade interne
D.
Euh, c'est quoi ces 'extern' devant des fonctions ?
Il manque un header : "client_telnet.h"
D'autre part, le ping ne fait qu'alourdir inutilement le code. A retirer.
Tu n'as pas besoin de ton IP pour faire une connexion. Tu as besoin de l'IP du serveur. Si c'est sur la même machine, tu mets 127.0.0.1.
oui je suis d'accord que le ping alordit méchamment, mais je ne sais pas comment faire autrement pour récuperer mon IP.
Pour les extern, je les ai mis parce que le compilo me reprochait de renvoyer des adresses de variables internes avant qu'ils soient mis.
Le header client-telnet.h qui suit, il vient de client_smtp.h qui sert à envoyer un mèl directement depuis du C; j'y ai juste modifié le numéro de port à utiliser.
voilou; et merci encore de regarder mon histoire, et comme je l'ai demandé en réponse à delete tout à l'heure, est ce que mon dialogue avec le serveur part sur de bonnes bases pour essayer de décrypter quand il me demande le login puis le password ?Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 #ifndef CLIENT_SMTP_H #define CLIENT_SMTP_H #ifdef WIN32 #include <winsock2.h> #elif defined (linux) // déjà inclus dans mtn.c #include <arpa/inet.h> #include <netdb.h> /* gethostbyname */ #include <netinet/in.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> /* close */ #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 #define closesocket(s) close(s) typedef int SOCKET; typedef struct sockaddr_in SOCKADDR_IN; typedef struct sockaddr SOCKADDR; typedef struct in_addr IN_ADDR; #else #error not defined for this platform #endif #define EHLO "EHLO" #define MAIL_FROM "MAIL FROM:" #define RCPT_TO "RCPT TO:" #define DATA "DATA" #define END_DATA "." #define QUIT "QUIT" #define PORT 23 //DVA; #define BUF_SIZE 1024 #define CRLF "\r\n" static void init(void); static void end(void); static void app(const char *buffer); static void read_server(SOCKET sock, char *buffer); static void write_server(SOCKET sock, char *buffer); // inutile j'espère pour mtn.c static void send_message(FILE *file, SOCKET sock, char *buffer); // inutile j'espère pour mtn.c static void get_line(FILE *file, char *buffer); // inutile j'espère pour mtn.c static void get_and_send_rcpts(SOCKET sock, FILE *file); #endif /* guard */ #ifndef CLIENT_SMTP_H #define CLIENT_SMTP_H #ifdef WIN32 #include <winsock2.h> #elif defined (linux) // déjà inclus dans mtn.c #include <arpa/inet.h> #include <netdb.h> /* gethostbyname */ #include <netinet/in.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> /* close */ #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 #define closesocket(s) close(s) typedef int SOCKET; typedef struct sockaddr_in SOCKADDR_IN; typedef struct sockaddr SOCKADDR; typedef struct in_addr IN_ADDR; #else #error not defined for this platform #endif #define EHLO "EHLO" #define MAIL_FROM "MAIL FROM:" #define RCPT_TO "RCPT TO:" #define DATA "DATA" #define END_DATA "." #define QUIT "QUIT" #define PORT 23 //DVA; #define BUF_SIZE 1024 #define CRLF "\r\n" static void init(void); static void end(void); static void app(const char *buffer); static void read_server(SOCKET sock, char *buffer); static void write_server(SOCKET sock, char *buffer); // inutile j'espère pour mtn.c static void send_message(FILE *file, SOCKET sock, char *buffer); // inutile j'espère pour mtn.c static void get_line(FILE *file, char *buffer); // inutile j'espère pour mtn.c static void get_and_send_rcpts(SOCKET sock, FILE *file); #endif /* guard */
David
J'ai toujours pas compris pourquoi tu voulais récupérer ton IP. Ce qui compte c'est l'IP du serveur.
Ca na aucun sens. Tu peux montrer le message d'erreur ?Citation:
Pour les extern, je les ai mis parce que le compilo me reprochait de renvoyer des adresses de variables internes avant qu'ils soient mis.
un simple et classiqueCitation:
Le header client-telnet.h qui suit, il vient de client_smtp.h qui sert à envoyer un mèl directement depuis du C; j'y ai juste modifié le numéro de port à utiliser.
aurait suffit, non ?Code:#define PORT 23
a part le coup de l'IP que je n'ai toujours pas pigé, oui, à peu près. je ne sais pas si c'est une bonne idée de supprimer le CRLF dans la chaine reçue...Citation:
voilou; et merci encore de regarder mon histoire, et comme je l'ai demandé en réponse à delete tout à l'heure, est ce que mon dialogue avec le serveur part sur de bonnes bases pour essayer de décrypter quand il me demande le login puis le password ?
J'ai un peu simplifié le code :
J'ai testé sur le serveur Telnet de mon routeur, et il me renvoit de l'écho évidemment 'des '*' quand on passe le mot de passe), avec toujours des caractères étranges au début.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233 #include "ed/inc/sys.h" #include "ed/inc/prt.h" #ifdef __cplusplus #error Be sure you are using a C compiler... #endif #if defined (WIN32) || defined (_WIN32) #include <winsock2.h> typedef size_t socklen_t; #elif defined (linux) || defined (_POSIX_VERSION) || defined (_POSIX2_C_VERSION)\ || defined (_XOPEN_VERSION) #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> /* close */ #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 #define closesocket(s) close (s) typedef int SOCKET; typedef struct sockaddr_in SOCKADDR_IN; typedef struct sockaddr SOCKADDR; #else #error not defined for this platform #endif #include <stdio.h> #include <stdlib.h> /* macros ============================================================== */ #define PORT 23 #define CRLF "\r\n" #define LIN_SIZE 80 #define BUF_SIZE 1024 /* constants =========================================================== */ /* types =============================================================== */ /* structures ========================================================== */ /* private data ======================================================== */ /* private functions =================================================== */ /* -------------------------------------------------------------------------- */ static int write_server (SOCKET sock, char const *buffer) { int err = 0; if (send (sock, buffer, strlen (buffer), 0) <= 0) { printf ("send error\n"); err = 1; } return err; } /* -------------------------------------------------------------------------- */ static int read_server (SOCKET sock, char *buffer, size_t size) { int err = 0; int n = recv (sock, buffer, size - 1, 0); if (n > 0) { buffer[n] = 0; #if 0 SYS_dump (buffer, n); #endif #if 0 { char *p = strstr (buffer, CRLF); if (p != NULL) { *p = 0; } } #endif } else { err = 1; if (n == 0) { printf ("read_server: Connection lost\n"); } else { printf ("read_server: error\n"); } } return err; } /* -------------------------------------------------------------------------- */ static int Stn (char const *serv_ip) { SOCKET sock = socket (AF_INET, SOCK_STREAM, 0); if (sock != INVALID_SOCKET) { int err; struct sockaddr_in sin = { 0 }; sin.sin_addr.s_addr = inet_addr (serv_ip); sin.sin_port = htons (PORT); sin.sin_family = AF_INET; err = connect (sock, (SOCKADDR *) & sin, sizeof (SOCKADDR)); if (err != SOCKET_ERROR) { char line[LIN_SIZE]; printf ("Stn: client connected with socket %d to %s:%d\n", sock, inet_ntoa (sin.sin_addr), htons (sin.sin_port)); /* */ printf ("Stn: invite de login :\n"); err = read_server (sock, line, sizeof line); /* lecture de l'invite de login */ if (!err) { puts (line); /* affichage de celle ci */ } if (!err) { char command[BUF_SIZE]; printf ("Stn: envoi de %s+\"%s\"\n\n", "guest", "CRLF"); sprintf (command, "%s%s", "guest", CRLF); err = write_server (sock, command); } if (!err) { err = read_server (sock, line, sizeof line); } if (!err) { printf ("%s", line); } } closesocket (sock); } #if 0 printf ("Stn: invite de password :\n"); read_server (sock, line); /* lecture de l'invite de password */ puts (line); /* affichage de celle ci */ printf ("Stn: envoi de %s+\"%s\"\n", "guest1", "CRLF"); sprintf (command, "%s%s", "guest1", CRLF); write_server (sock, command); /* */ read_server (sock, line); puts (line); /* */ printf ("Stn: end of trial.\n"); /* on n'arrive pas encore ici, tu rêves ??? */ #endif return 0; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ static int main_ (void) { #if 0 #define IP "127.0.0.1" #else #define IP "192.168.0.1" #endif Stn (IP); return 0; } /* entry point ========================================================= */ /* --------------------------------------------------------------------- --------------------------------------------------------------------- */ int main (void) { int ret; #if defined (WIN32) WSADATA wsa_data; int err = WSAStartup (MAKEWORD (2, 2), &wsa_data); if (!err) { puts ("WIN: winsock2: OK"); #else int err; #endif main_ (); #if defined (WIN32) WSACleanup (); } #endif if (err) { ret = EXIT_FAILURE; } else { ret = EXIT_SUCCESS; } return ret; }
Tu peux me donner l'IP de ton serveur Telnet par MP, juste pour savoir ce qu'il envoie au moment de la connexion.Code:
1
2
3
4
5
6
7
8
9
10
11 WIN: winsock2: OK Stn: client connected with socket 68 to 192.168.0.1:23 Stn: invite de login : *¹♥*¹☺ Password: Stn: envoi de guest+"CRLF" * Process returned 0 (0x0) execution time : 0.057 s Press any key to continue.
Salut Emmanuel;
je suis archi-content d'avoir encore des réponses pour me permettre d'avancer un peu. (et d'après ce que j'ai vu avant de copier la chose qui suit, y'en a pas mal; YOUPI)
Eh bien c'est parce que je préfère faire des essais sur mon propre serveur telnet, que j'ai mis en place il y a quelques jours, plutôt que sur celui du boulot qui risque d'en avoir marre d'avoir à s'occuper de mon client tout pourri; donc j'ai besoin de ma propre IP pour accéder à mon propre serveur telnet. (c'est juste par facilité)Citation:
J'ai toujours pas compris pourquoi tu voulais récupérer ton IP. Ce qui compte c'est l'IP du serveur.
Je ne l'ai évidemment plus, mais je vais essayer d'enlever les extern sur un version qui marche que j'ai heureusement sauvegardée et je reviens ici te coller ça dans dix minutes...Citation:
Tu peux montrer le message d'erreur ?
[.../...]
...bon ben les dix minutes sont écoulées et j'ai viré tous les extern et le compilo s'en balance, donc Ok bien vu cher Monsieur.
Peur-être bien mais comme j'y connais pas grand chose, j'ai tout gardé, mais j'essairai de simplifier au maximum....Citation:
[#define...] aurait suffit, non ?
[.../...]
..hébin justement je viens de lire ton code, et y'en a un maximum, des simplifications; je t'envoie mon IP dès que le serveur veut bien me laisser envoyer des MP parce que quand je suis en train de rédiger c'est bloqué.
alors MERCI et à bientôt,
David
PS. en me connectant par telnet sur ma propre IP, je l'ai vue la chaine d'acceuil, mais merci encore.
D.
Ton serveur envoie ceci :
Ce qui doit faire partie de la négociation. Il faut étudier le protocole Telnet pour savoir ce qu'il faut renvoyer, pourquoi, comment etc. Ça ne s'invente pas. Je ne connais pas ce protocole.Code:
1
2
3
4
5
6
7
8
9 WIN: winsock2: OK Stn: client connected with socket 68 to xxx.xxx.xxx.xxx:23 Stn: invite de login : 0022F960 FF FD 18 FF FD 20 FF FD 23 FF FD 27 '..... ..#..'' *²↑*² *²#*²' Process returned 0 (0x0) execution time : 0.356 s Press any key to continue.
Pour cela il y a les RFC. Pour telnet http://www.rfc.net/rfc854.html
Après il y a toutes les RFC sous&adjacentes... notamment sur la gestion des TTY.
Une petite recherche GG ?
Salut les totos; dimanche matin quand j'ai lu les posts qu'ont mis Emmanuel et delete samedi soir, je me suis souvenu du fil de discussion dont j'ai déjà parlé ci dessus au post du 26 août (qui n'était jamais que mercredi dernier, et donc grace à vous, merci encore, j'ai super-bien avancé, parce que j'ai repris ce code, qui ne marchait pas uniquement parce qu'il entamait la négociation sans être bien connecté, et qu'il se mélangeait un peu les pédales dans les différents descripteurs de la fonction select) ...et donc ce fil dont je me suis souvenu établissait une négociation d'ouverture de session telnet; et grace à cela, je suis en train de me bagarrer avec les options et les sous-options qui sont décrites dans la RFC que m'a indiquée delete, et c'est un gros délire, mais avec un soupçon de persévérance je sais que j'y arriverai, même si le soupçon se mesure ici en mégatonnes.
à bientôt,
David
Il est tard mais j'ai encore une question assez cruciale qui me taraude; mon programme plante dans la négociation avec le serveur telnet juste au niveau d'une écriture sur le socket (alors qu'il en a déjà fait plusieurs avec succès) donc je soupçonne le socket de ne pas être prêt à avaler ça; donc je voudrais le contrôler avec FD_ISSET(sock, &wr) (c'est une macro mais je suppose qu'elle est assez classique pour ne pas avoir à la détailler) et il se trouve que cette écriture sur le socket (que je soupçonne de faire planter le programme) se fait dans une fonction différente de celle dans laquelle les ensembles de descripteurs &rd et &wr ont été définis; seront ils toujours valides, ou dois-je les externaliser ou faut il les re-créer dans cette autre routine ?
David (qui commence à poser des questions plus balèzes me semble-t'il)
[mardi 18h32]Tant mieux parce que l'utilisation du select pour contrôler ne doit pas être ce que je fais de mieux.Citation:
Peu probable
-Contrôler que le socket sur le quejl je tente d'écrire est bien connecté à mon propre serveur. -Ok
-Vérifier aussi que les toutes premières requêtes ont été écrites correctement sur le socket. -Ok
-Vérifier aussi la prise en compte de ces requêtes. (et éventuellement des suivantes) -Apparemment oui puisque le dialogue semble sensé.
-Modifier le code pour que les descripteurs d'E-S, &rd et &wr, soient définis dans le main, et qu'il les passe en arguments à la fonction qui s'en sert, pour les avoir toujours sous la main plus tard, comme par exemple au moment de l'écriture qui tue. -Apparemment inutile d'après la réponse d'Emmanuel et c'est tant mieux.
[mardi vers une heure]
Salut les messieurs du net'; j'écris depuis le boulot et je m'enverrai ce mèl chez moi tout à l'heure pour le poster ce soir après être arrivé; je le posterai après l'avoir modifié si jamais vous avez posté des informations qui me font modifier mon code et que le résultat change du tout au tout, ou alors si les premiers contrôles que je me suis aperçu qu'il fallait que je fasse exigent aussi une telle modification.
Mais pour l'instant je considère que j'en suis à la situation d'hier soir que je vais essayer de récapituler, ce qui m'éclaircira les idées et me fournira peut-être une issue à mon problème à laquelle je n'aurais pas pensé si j'étais resté la tête dans le guidon; et en outre c'est parti pour faire un beau pavé que je sais que vous allez apprécier.
Donc je veux faire un programme qui se logge par telnet sur une adresse IP que je lui fournis et me laisse la main sur l'invite de commandes de la machine serveur (au boulot) pour que je puisse contrôler les calculs que j'ai lancés dans la journée et en relancer d'autres après avoir succintement modifié les données par vi, ça me suffit; pour l'instant je lui fournis la mienne propre, d'adresse IP, pour qu'il essaie de se logger sur un serveur telnet que j'ai mis en place sur ma propre machine aussi, pour des essais.
Or, le protocole de communication qui régit telnet, stipule qu'il y ait une phase de négociation entre les deux machines avant l'ouverture de la session; (pour décider à quelle vitessse ils vont se causer, quel terminal utilise chacun, etc)
Je sais que ce protocole est en partie défini dans des documents en anglais nommés RFC 854, 55, ... (comme Request For Comments); j'en ai lu un peu mais je ne parviens pas à trouver où est présentée une sous option 32 de la négociation, où ils décident de la "Terminal Speed", et malheureusement mon programme plante à ce niveau là et je n'arrive pas à me documenter sur ce que je dois lui envoyer.
La gamelle se produit (de mémoire) au moment où je tente d'écrire sur le socket du modem; (je crois que ce socket est bien connecté à mon propre serveur mais je contrôlerai ça aussi ce soir avant toute autre chose) je tente d'y écrire une réponse à un message de négociation à propos de cette "Terminal Speed". Autant que je me souvienne, il y a déjà eu plusieurs écritures sur ce socket, puisque le tout début de la négociation consiste en plusieurs envois à sens unique, de ma part vers le serveur; cependant je ne sais pas dans quelle mesure ces requêtes ont été prises en compte. (donc il faut que je vérifie ça aussi dès que je suis rentré et avant toute autre chose, ainsi que la mesure dans laquelle ces requêtes ont été honorées)
Il est possible que l'écriture sur le socket ne soit pas possible parce que celui ci n'est pas disponible dans ce but, et je voudrais vérifier cette disponibilité par la fonction "select" que j'ai déjà utilisé ailleurs dans le programme. Je l'avais utilisée dans une fonction précédente de ce "main" qui tente de se logger, et je ne suis pas sûr que les decripteurs de canaux que j'avais utilisés dans cette fonction (&rd et &wr) soient encore valides quand on est remonté dans le "main".
Ils ne sont probablement plus définis, et donc il faudrait que ce soit le "main" lui même qui les définisse avant d'appeler la fonction qui les utilise la première, en les lui passant en arguments.
Ainsi j'aurais à ma disposition de quoi contrôler la disponibilité du socket pour écrire la réponse de négociation qui tue.
David
voici ce que j'obtiens comme sortieCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 david@test:~/Skul1-telnet$ sudo ./mtn wanadoo.fr [sudo] password for david: monip: Ok pour le premier socket qui sert au ping. monip: h->h_name=wanadoo.fr (résolu par gethostbyname sur ce socket qui est pingsock) imppkt: Ok impression du paquet envoyé : imppkt: type=8, code=0, chksum=65527 monip: adresse dest.=1736113345 monip: long2ip(1736113345) => 103.122.252.193 monip: host de dest.=wanadoo.fr (le même h->h_name que résolu ci dessus) monip: avant recvfrom monip: Ok après recvfrom monip: wanadoo.fr is alive ! imppkt: Ok impression du paquet reçu : imppkt: type=0, code=0, chksum=65535 monip: adresse source=1736113345 long2ip(1736113345) => 103.122.252.193 monip: host de source du retour=hpwoo.wanadooportails.com (hh->h_name) monip: gethostbyaddr() Ok monip: adresse src du retour=103.122.252.193 monip: adr. dst nr du retour=82.125.13.224 mtn: monIP=82.125.13.224 mtn: ici Stn: là, monIP=82.125.13.224 (=1383927264 en %u) Stn: Contrôles : Stn: sin.sin_port=23 Stn: sin.sin_family=2 Stn: sin.sin_addr.s_addr=3758980434, (=224.13.125.82) (nr) Stn: try to connect : Stn: connect() Ok, connexion=0 Stn: connection=0 OK valeur du timeout 110 MSG_DE_NEGO: demande des negos initiales DO ECHO DO SUPPRESS GO AHEAD WILL NAWS MSG_DE_NEGO: fin de la nego. initiale DVA: ntour=1 DVA: select(sock+1,&rd,&wr,NULL,&delai)=2 DVA: ntour=3002 DVA: select(sock+1,&rd,&wr,NULL,&delai)=2 DVA: ntour=11412 DVA: select(sock+1,&rd,&wr,NULL,&delai)=3 valeur de verif_select = 3 Debut de nego valeur de j=2 valeur des octets reçus: octet 0= 255 octet 1= 253 octet 2= 24 N° traitement des types de message 255 253 24 valeur de la socket 3 DO 253 demande de negociation Procedure OPTION_NEGOCIEE, *(mess_nego2+2)=24 Option Terminal type Option Terminal type sens de requet 255 253 24 0 Reponse envoyee i= 3, 255 251 24 0 Debut de nego valeur de j=2 valeur des octets reçus: octet 0= 255 octet 1= 253 octet 2= 32 N° traitement des types de message 255 253 32 valeur de la socket 3 DO 253 demande de negociation Procedure OPTION_NEGOCIEE, *(mess_nego2+2)=32 Option Terminal speed Sous option Terminal speed N° 32 Option Terminal speed sens de requet 32 OK ici OK là Option Terminal speed sens requet 255 253 32 *** glibc detected *** ./mtn: double free or corruption (fasttop): 0x0804fbc0 *** ======= Backtrace: =========/lib/tls/i686/cmov/libc.so.6[0xb7e6ba85] /lib/tls/i686/cmov/libc.so.6(cfree+0x90)[0xb7e6f4f0] ./mtn[0x804af03] ./mtn[0x804b205] /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7e16450] ./mtn[0x8048d31] ======= Memory map: ======== 08048000-0804d000 r-xp 00000000 07:00 597165 /home/david/Skul1-telnet/mtn 0804d000-0804e000 rw-p 00004000 07:00 597165 /home/david/Skul1-telnet/mtn 0804e000-0806f000 rw-p 0804e000 00:00 0 [heap] b7c00000-b7c21000 rw-p b7c00000 00:00 0 b7c21000-b7d00000 ---p b7c21000 00:00 0 b7d63000-b7d6d000 r-xp 00000000 07:00 922144 /lib/libgcc_s.so.1 b7d6d000-b7d6e000 rw-p 0000a000 07:00 922144 /lib/libgcc_s.so.1 b7d6e000-b7d7d000 r-xp 00000000 07:00 939766 /lib/tls/i686/cmov/libresolv-2.7.so b7d7d000-b7d7f000 rw-p 0000f000 07:00 939766 /lib/tls/i686/cmov/libresolv-2.7.so b7d7f000-b7d81000 rw-p b7d7f000 00:00 0 b7d81000-b7d85000 r-xp 00000000 07:00 939753 /lib/tls/i686/cmov/libnss_dns-2.7.so b7d85000-b7d87000 rw-p 00003000 07:00 939753 /lib/tls/i686/cmov/libnss_dns-2.7.so b7d87000-b7d89000 r-xp 00000000 07:00 922175 /lib/libnss_mdns4_minimal.so.2 b7d89000-b7d8a000 rw-p 00001000 07:00 922175 /lib/libnss_mdns4_minimal.so.2 b7d96000-b7d97000 rw-p b7d96000 00:00 0 b7d97000-b7ee0000 r-xp 00000000 07:00 939738 /lib/tls/i686/cmov/libc-2.7.so b7ee0000-b7ee1000 r--p 00149000 07:00 939738 /lib/tls/i686/cmov/libc-2.7.so b7ee1000-b7ee3000 rw-p 0014a000 07:00 939738 /lib/tls/i686/cmov/libc-2.7.so b7ee3000-b7ee6000 rw-p b7ee3000 00:00 0 b7ee6000-b7eef000 r-xp 00000000 07:00 939755 /lib/tls/i686/cmov/libnss_files-2.7.so b7eef000-b7ef1000 rw-p 00008000 07:00 939755 /lib/tls/i686/cmov/libnss_files-2.7.so b7ef1000-b7ef4000 rw-p b7ef1000 00:00 0 b7ef4000-b7ef5000 r-xp b7ef4000 00:00 0 [vdso] b7ef5000-b7f0f000 r-xp 00000000 07:00 922099 /lib/ld-2.7.so b7f0f000-b7f11000 rw-p 00019000 07:00 922099 /lib/ld-2.7.so bff01000-bff16000 rw-p bffeb000 00:00 0 [stack] OK encore iciAbandon david@test:~/Skul1-telnet$
...et voici le code qui produit cet heureux cafouillage...
Je n'ai pas encore tout compris mais je me l'approprie petit à petit et il peut vous servir pour trouver la raison d'un comportement qui vous paraîtrait bizare.
Merci si vous y jetez un oeil ou si ce qui se passe vous inspire des réflexions intéressantes.
David
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387 // Ceci est un essai pour comprendre ce qui se passe avec le net; mtn est après le ping. // je veux que ce programme S du telnet chez moi; mtn=mon telnet. // gcc mtn.c -o mtn // "./mtn host" pour résolver l'host et s'y connecter un jour j'espère. // sudo ./mtn wanadoo.fr // // rappels sur les pointeurs : // &truc est l'adresse de truc // ptruc = &truc, l'adresse en question. // ptruc prend la même place qu'un entier, quel que soit le type de l'objet sur lequel il pointe. // int *ptruc; // ici, il pointera sur un entier. // int n=10; // n est un entier initialisé à 10. // ptruc=&n; // ptruc pointe sur n auquel on assède par *ptruc // *ptruc+=5; // l'objet sur lequel pointe ptruc est augémenté de cinq. // à partir d'ici, n vaut quinze. // // #include <arpa/inet.h> // #include "client_telnet.h" #include <errno.h> #include <netdb.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> // définit ICMP_ECHO et ICMP_ECHOREPLY. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/file.h> #include <sys/param.h> #include <sys/signal.h> #include <sys/socket.h> #include <sys/time.h> #include <sys/times.h> #include <termios.h> #include <unistd.h> // // #define BUF_SIZE 1024 #define CRLF "\r\n" #define DEFDATALEN 56 // #define ETIMEDOUT 30 #define LG_BUFFER 1 #define LIN_SIZE 80 #define MAXICMPLEN 76 #define MAXIPLEN 60 #define PORT 23 #define SOCKET_ERROR -1 // // typedef int SOCKET; typedef struct sockaddr SOCKADDR; // // /* N° d'option a negocier */ OPTION_NEGOCIEE(mess_nego,socket11) // ici on fait des write sur le socket... { struct termios terminal_out; speed_t speed_o,speed_i; int socket12, i, k, j; unsigned char *mess_nego2, *rep_mess_nego; socket12=socket11; mess_nego2=mess_nego; printf("\nProcedure OPTION_NEGOCIEE, *(mess_nego2+2)=%d",*(mess_nego2+2)); switch (*(mess_nego2+2)) { case 1: { printf ("\n Option ECHO"); if (*(mess_nego2+1)==253) // 253=DO { printf("\nreponse %d %d %d %d",*(mess_nego2+0),*(mess_nego2+1)=252,*(mess_nego2+2),*(mess_nego2+3)); i=write(socket11,mess_nego2,4); } } break; case 3: { printf ("\n Option GA"); if(*(mess_nego2+1)==253) // 253=DO { printf("\nReception du WILL pour GA"); *(mess_nego2+1)=251; } printf("\nmessage envoye %d %d %d",*(mess_nego2+0),*(mess_nego2+1),*(mess_nego2+2)); i=write(socket11,mess_nego2,3); } break; case 24: { printf ("\n Option Terminal type"); printf ("\n Option Terminal type sens de requet %d %d %d %d",*(mess_nego2+0),*(mess_nego2+1),*(mess_nego2+2),*(mess_nego2+3)); *(mess_nego2+1)=251; // 251=WILL i=write(socket11,mess_nego2,3); printf("\nReponse envoyee i= %d, %d %d %d %d",i,*(mess_nego2+0),*(mess_nego2+1),*(mess_nego2+2),*(mess_nego2+3)); } break; case 31: { printf("\nOption NAWS"); /*printf("\nEnvoi de la sous option direct");*/ if((mess_nego2=realloc(mess_nego2,10*sizeof(unsigned char)))==NULL) printf("\nrealloc echouee sur SB 31"); *(mess_nego2+0)=255; // 255=IAC *(mess_nego2+1)=250; // 250=SB Indicates that what follows is subnegotiation of the indicated option. *(mess_nego2+2)=31; *(mess_nego2+3)=0; *(mess_nego2+4)=80; *(mess_nego2+5)=0; *(mess_nego2+6)=24; *(mess_nego2+7)=255; // 255=IAC *(mess_nego2+8)=240; // 240=SE End of subnegotiation parameters printf("\nmessage a envoye %d %d %d %d %d %d %d %d",*(mess_nego2+0),*(mess_nego2+1),*(mess_nego2+2),*(mess_nego2+3),*(mess_nego2+4),*(mess_nego2+5),*(mess_nego2+6),*(mess_nego2+7)); i=write(socket11,mess_nego2,9); printf("\nReponse NAWS envoyee"); } break; case 32: // quand cette sous-option arrive ça fait tout planter, donc j'essaye un WON'T-252 { printf("\nOption Terminal speed"); printf("\nSous option Terminal speed N° 32"); printf ("\nOption Terminal speed sens de requet %d",*(mess_nego2+2)); // S avec 2 au lieu de 3 -Ok printf ("\nOK ici"); *(rep_mess_nego+0)=255; // 255=IAC *(rep_mess_nego+1)=252; // WON'T *(rep_mess_nego+2)=32; // 32-Terminal speed printf ("\nOK là"); printf ("\nOption Terminal speed sens requet %d %d %d",*(mess_nego2+0),*(mess_nego2+1),*(mess_nego2+2)); // ICICICICI SELECT ISSET // printf("DVA: FD_ISSET(sock, &wr)=%d\n",FD_ISSET(socket11, &wr)); write(socket11,rep_mess_nego,3); // 3 octets renvoyés. printf ("\nOK encore ici"); } break; case 33: { printf ("\nOption LFLOW"); printf("\nvaleur de j=%d \n valeur des octets reçus: ",j=strlen(mess_nego)); for(k=0;k<j+1;k++) printf("\noctet %d= %d ",k,*(mess_nego2+k)); /*if (*(mess_nego2+1)==253) // 253=DO { if((mess_nego2=realloc(mess_nego2,6*sizeof(unsigned char)))==NULL) printf("\n Erreur fatal reallocation de memoire OPTION_NEGOCIEE N° 33"); *(mess_nego2+0)=255; // 255=IAC *(mess_nego2+1)=250; *(mess_nego2+2)=33; *(mess_nego2+3)=3; *(mess_nego2+4)=255; // 255=IAC *(mess_nego2+5)=240; printf("\nReponse %d %d %d ",*(mess_nego2+0),*(mess_nego2+1),*(mess_nego2+2)); i=write(socket12,mess_nego2,6); printf("\nMessage reponse envoyé %d %d %d %d %d %d ",*(mess_nego2+0),*(mess_nego2+1),*(mess_nego2+2),*(mess_nego2+3),*(mess_nego2+4),*(mess_nego2+5)); }*/ } break; /*case 36: printf("\nOption d'environnement");*/ /*break;*/ default: { printf("\n%d option inconnue ou non negociee",*(mess_nego2+2)); /*for(i=0;i<sizeof(mess_nego2);i++) printf(" i=%d mess_nego= %d",i,*(mess_nego2+i)); if (*(mess_nego2+1)==251) *(mess_nego2+1)=254; else *(mess_nego2+1)=252; printf("\nreponse envoyee: "); for(i=0;i<sizeof(mess_nego2);i++) printf(" i=%d mess_nego= %d",i,*(mess_nego2+i));*/ write(socket12,mess_nego2,sizeof(mess_nego2)); } break; free(mess_nego2); } } // /* Sous option negociee */ SOUS_OPTION_NEGOCIEE(mess_nego,socket11) { int i,j; unsigned char *terminal,*mess_nego3,*rep_mess_nego,*vitesse,DEB_SB,FIN_SB,donnee[4]; struct termios terminal_out; speed_t speed_o,speed_i; mess_nego3=mess_nego; DEB_SB=250; FIN_SB=240; donnee[0]="9"; donnee[1]="6"; donnee[2]="0"; donnee[3]="0"; printf("\nProcedure SOUS_OPTION_NEGOCIEE sous option a negocier valeur de la SB %d",*(mess_nego3+2)); switch (*(mess_nego3+2)) { case 24:{ /*Recuperation d'info sur le terminal*/ printf("\nSous option Type de terminal actuel: %s,\nlongueur de la chaine terminal %d,\nsizeof de messnego13 %d,\nstrlen+sizeof %d,\nstrlen de messnogo13 %d",terminal=getenv("TERM"),strlen(terminal),sizeof(mess_nego3),i=(strlen(terminal)+strlen(mess_nego3)),strlen(mess_nego3)); printf("\nsequence recue taille du message %d %d %d %d %d %d",*(mess_nego3+0),*(mess_nego3+1),*(mess_nego3+2),*(mess_nego3+3),*(mess_nego3+4),*(mess_nego3+5)); if((mess_nego3=realloc(mess_nego3,(i+1)*sizeof(unsigned char)))==NULL) printf("\nrealloc echouee sur SB 24"); printf("\ntaille de mess_nego3 %d",strlen(mess_nego3)); if((terminal=(char*) calloc (strlen(getenv("TERM")),sizeof (char)))==NULL) printf("\nImpossible d'allouer la memoire terminal"); terminal=getenv("TERM"); *terminal=toupper(*terminal); printf("\nterminal =%s",terminal); /*strcpy(terminal,getenv("TERM");*/ toupper(*terminal); printf("\nContenu de terminal :%s",*terminal); printf("\nen majuscule"); for(j=0;j<(strlen(getenv("TERM")));j++) { *(terminal+j)=toupper(*(terminal+j)); printf("%d %c",j,*(terminal+j)); } strcat(mess_nego3,terminal); printf("\nsequence du message modifié %d %d %d %d %d %d ",*(mess_nego3+0),*(mess_nego3+1),*(mess_nego3+2),*(mess_nego3+3)=0,*(mess_nego3+4),*(mess_nego3+5)); printf("\nchaine de terminal %s",terminal); memmove((mess_nego3+4),terminal,strlen(terminal)+1); printf("\nsequence recue modifiee %d %d %d %d %c%c%c%c%c%c %d %d %d",*(mess_nego3+0),*(mess_nego3+1),*(mess_nego3+2),*(mess_nego3+3)=0,*(mess_nego3+4),*(mess_nego3+5),*(mess_nego3+6),*(mess_nego3+7),*(mess_nego3+8),*(mess_nego3+9),*(mess_nego3+10)=255,*(mess_nego3+11)=240,*(mess_nego3+12)=0); // 255=IAC i=write(socket11,mess_nego3,13); printf("\nnombre de caracteres ecris= %d\n",i); i=write(1,"mess_nego3",13); printf("\ndeuxieme valeur de i=%d",i); free (mess_nego3); } break; // case 32:{ printf("\nSous option Terminal speed"); printf("\nsequence recue taille du message %d %d %d %d %d %d %d %d",*(mess_nego3+0),*(mess_nego3+1),*(mess_nego3+2),*(mess_nego3+3),*(mess_nego3+4),*(mess_nego3+5),*(mess_nego3+6),strlen(mess_nego3)); printf("\nRecuperation de la vitesse du terminal"); // printf ("\nOK icii"); *(rep_mess_nego+1)=252; // WON'T *(rep_mess_nego+2)=32; // 32-Terminal speed printf ("\nOK làà"); write(socket11,rep_mess_nego,3); // pas d'autre argument donc seuleument 2 octets renvoyés XXX si, 3. printf ("\nOK encore ici"); // /* tcgetattr(STDIN_FILENO,&terminal_out); speed_o=cfgetospeed(&terminal_out); */ /*printf("\nvitesse du terminal en out %d",speed_o);*/ /* if((mess_nego3=realloc(mess_nego3,(strlen(mess_nego3)+11)*sizeof(unsigned char)))==NULL) printf("\nrealloc echouee sur SB 32"); */ /*printf("\nmodification du *(mess_nego3+3) %d",*(mess_nego3+3)=0);*/ /* i=write(1,"mess_nego3",13); */ free (mess_nego3); } break; // case 33:{ printf("\nSous option LFLOW"); printf("\nsequence recue taille du message %d %d %d %d %d %d",*(mess_nego3+0),*(mess_nego3+1),*(mess_nego3+2),*(mess_nego3+3),*(mess_nego3+4),*(mess_nego3+5)); switch (*(mess_nego3+3)) { case 0:{ printf("\nDans case 0 mess_nego3+3= %d",*(mess_nego3+3)); /**(mess_nego3+3)=2; printf("\nRéponse %d %d %d %d %d %d",*(mess_nego3+0),*(mess_nego3+1),*(mess_nego3+2),*(mess_nego3+3),*(mess_nego3+4),*(mess_nego3+5)); i=write(socket11,mess_nego3,6);*/ } break; case 3:{ printf("\nDans case3 mess_nego3+3= %d",*(mess_nego3+3)); /**(mess_nego3+3)=4; printf("\nRéponse %d %d %d %d %d %d",*(mess_nego3+0),*(mess_nego3+1),*(mess_nego3+2),*(mess_nego3+3),*(mess_nego3+4),*(mess_nego3+5)); i=write(socket11,mess_nego3,6);*/ } break; printf("\nRéponse %d %d %d %d %d %d",*(mess_nego3+0),*(mess_nego3+1),*(mess_nego3+2),*(mess_nego3+3),*(mess_nego3+4),*(mess_nego3+5)); default:printf("\nDans default mess_nego3+3= %d",*(mess_nego3+3)); break; } } break; // case 36: printf("\nSous option environnement"); break; // default: printf("\nSous option non negociee"); break; } } // /*negociation de depart*/ MSG_DE_NEGO(sock) { unsigned char mesg_nego[7]; printf("\nMSG_DE_NEGO: demande des negos initiales"); // printf("\nDO ECHO"); mesg_nego[0]=255; /*IAC*/ mesg_nego[1]=253; /*DO*/ mesg_nego[2]=1; /*ECHO*/ mesg_nego[3]=0; write(sock,mesg_nego,3); // printf("\nDO SUPPRESS GO AHEAD"); mesg_nego[0]=255; /*IAC*/ mesg_nego[1]=253; /*DO*/ mesg_nego[2]=3; /*SUPPRESS GO AHEAD*/ write(sock,mesg_nego,3); // //printf("\nWILL TERMINAL TYPE"); //mesg_nego[0]=255; /*IAC*/ //mesg_nego[1]=251; /*WILL*/ //mesg_nego[2]=24; /*TERMINAL TYPE*/ /*write(sock,mesg_nego,3);*/ // printf("\nWILL NAWS"); mesg_nego[0]=255; /*IAC*/ mesg_nego[1]=251; /*WILL*/ mesg_nego[2]=31; /*TAILLE TERMINAL NAWS*/ write(sock,mesg_nego,3); // mesg_nego[0]=255; /*IAC*/ mesg_nego[1]=251; /*WILL*/ mesg_nego[2]=32; /*TERMINAL SPEED*/ /*write(sock,mesg_nego,3);*/ // mesg_nego[0]=255; /*IAC*/ mesg_nego[1]=251; /*WILL*/ mesg_nego[2]=33; /* REMOTE FLOW CONTROL */ write(sock,mesg_nego,3); // /*mesg_nego[1]=250; */ // 250=SB Indicates that what follows is subnegotiation of the indicated option. /*mesg_nego[3]=1; */ /*mesg_nego[4]=255; */ // 255=IAC /*mesg_nego[5]=240; */ /*write(sock,mesg_nego,3); */ // printf("\nMSG_DE_NEGO: fin de la nego. initiale"); printf("\n\n"); } // /* procedure de negociation d'option telnet */ NEGOCIATION(buffer_RX, sock, i) // buffer_RX semble être ce que l'on reçoit { unsigned char *mess_nego, *rep_mess_nego; int socket11, j, k; socket11=sock; j=i; rep_mess_nego=mess_nego=buffer_RX; printf("\n\nDebut de nego"); printf("\nvaleur de j=%d \n valeur des octets reçus: ",j); for(k=0; k<j+1; k++) // donc j serait la taille en octets du message, moins un; j==2 si 3 octets printf("\noctet %d= %d ", k, *(mess_nego+k)); printf("\nN° traitement des types de message %d %d %d valeur de la socket %d",*mess_nego,*(mess_nego+1),*(mess_nego+2),sock); switch(*(mess_nego+1)) { case 250: // SB printf("\nSB %d demande de sous negociation",*(mess_nego+1)); SOUS_OPTION_NEGOCIEE(mess_nego,socket11); break; case 251: // WILL printf("\nWILL %d demande de negociation",*(mess_nego+1)); OPTION_NEGOCIEE(mess_nego,socket11); break; case 252: // WON'T printf("\nWONT %d refus de negociation",*(mess_nego+1)); OPTION_NEGOCIEE(mess_nego,socket11); *(rep_mess_nego+1)=254; // DON'T *(rep_mess_nego+2)=32; // 32-Terminal speed write(socket11,rep_mess_nego,3); printf("\nReponse a WONT = %d %d %d",*(rep_mess_nego+0),*(rep_mess_nego+1),*(rep_mess_nego+2)); break; case 253: // DO printf("\nDO %d demande de negociation",*(mess_nego+1)); OPTION_NEGOCIEE(mess_nego,socket11); break; case 254: printf("\nDONT %d refus de negociation",*(mess_nego+1)); /* OPTION_NEGOCIEE(mess_nego,socket11); */ *(rep_mess_nego+1)=252; write(socket11,rep_mess_nego,3); printf("\nReponse a DON'T = %d %d %d",*(rep_mess_nego+0),*(rep_mess_nego+1),*(rep_mess_nego+2)); break; default: printf("\nErreur de traitement sur negociation N° option %d",*(mess_nego+1)); break; } }
...et voici la suite du code puisque tout ne tient pas dans un seul post :
ici il y a le main précédé de la fonction qui fait un ping pour lire mon adresse IP dans l'en-tête de la réponse, puis celle qui se connecte et tente d'ouvrir une session.(Stn)
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482 // // Send ICMP ECHO_REQUEST packets to network hosts ///////////////////////////// static void ping(const char *host); //////////////////////////////////////////// // // static char *hostname = NULL; // préalable rassurant. // // static int in_cksum(unsigned short *buf, int sz) /////////////////////////////// { int nleft = sz; int sum = 0; unsigned short *w = buf; unsigned short ans = 0; // while (nleft > 1) { sum += *w++; nleft -= 2; } // if(nleft == 1) { *(unsigned char *) (&ans) = *(unsigned char *) w; sum += ans; } // sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); ans = ~sum; return(ans); } // // static int imppkt(struct icmp pkt, char *sens) ///////////////////////////////// { printf("\nimppkt: Ok impression du paquet %s :\n",sens); printf("imppkt: type=%u, code=%u, chksum=%u\n",pkt.icmp_type,pkt.icmp_code,pkt.icmp_cksum); return(0); } // // unsigned int ip2long(char *s) ////////////////////////////////////////////////// { struct sockaddr_in n; inet_aton(s,&n.sin_addr); return ntohl(n.sin_addr.s_addr); } // // char* long2ip(unsigned int v) ////////////////////////////////////////////////// { struct in_addr x; x.s_addr=htonl(v); // passe dans l' ordre reseau return inet_ntoa(x); // et convertit } // // char* long2ipnr(unsigned int v) ////////////////////////////////////////////////// { struct in_addr x; x.s_addr= v; // ne passe pas dans l' ordre reseau return inet_ntoa(x); // et convertit } // // static void noresp(int ign) //////////////////////////////////////////////////// { printf("noresp: No response from %s\n", hostname); exit(0); } // // static void read_server(SOCKET sock, char *buffer) { char *p; int n = 0; printf("read_server: sock=%d\n", sock); // ici, sock est un entier qui a été creéé par // // connect(sock,(SOCKADDR *) &sin, sizeof(SOCKADDR)) , et // // juste avant, on avait sock qui était une socket en stream : // // SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); { if((n = recv(sock, buffer, BUF_SIZE - 1, 0)) < 0) { perror("recv()"); exit(errno); } if(n == 0) { printf("read_server: Connection lost\n"); exit(EXIT_FAILURE); } buffer[n] = 0; p = strstr(buffer, CRLF); if(p != NULL) { *p = 0; } } } // // static void write_server(SOCKET sock, char *buffer) { if(send(sock, buffer, strlen(buffer), 0) < 0) { perror("send()"); exit(errno); } } // // char* monip(int argc, const char *host) //////////////////////////////////////// { struct hostent *h, *hh; // h et hh pointent sur des structures hostent. // h est celle obtenue avant le ping-aller par gethostbyname(mon isp) // hh est celle obtenue avant le pong-retour par gethostbyaddr(sonIP) struct icmp *pkt; // pkt pointe sur une structure icmp. struct sockaddr_in pingaddr, sin; char *pmonIP; unsigned long addr; // le paquet a été envoyé là bas int c, pingsock, selectold=0, type; char buffer[16]; char command[BUF_SIZE]; char line[LIN_SIZE]; char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; // packet est un tableau de caractères. socklen_t len; // SOCKADDR_IN sin; // déjà définie qq lignes + haut // SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); // à quoi ça sert ??? // if(argc<2 || strcmp(host,"-h")==0) { printf("\nmonip: Ce programme doit résolver [host],\n"); printf("monip: puis y envoyer un echorequest,\n"); printf("monip: puis en contrôler la teneur et la destination,\n"); printf("monip: puis contrôler la teneur et la provenance du retour.\n\n"); printf("monip: Ex: sudo ./mtn wanadoo.fr\n\n"); exit(1); } // if((pingsock = socket(AF_INET, SOCK_RAW, 1)) < 0) { // 1 == ICMP perror("monip: creating a raw socket"); exit(1); } else printf("\nmonip: Ok pour le premier socket qui sert au ping.\n"); // // drop root privs ifrunning setuid setuid(getuid()); // memset(&pingaddr, 0, sizeof(struct sockaddr_in)); // memset() remplit les n premiers octets // (avec n=sizeof(struct sockaddr_in)) de la zone mémoire pointée par s (s=&pingaddr) // avec loctet c (c=0). pingaddr.sin_family = AF_INET; // pingaddr est la struct sockaddr_in pour laquelle // vient d'être allouée de la mem. if(!(h = gethostbyname(host))) { fprintf(stderr, "monip: unknown host %s\n", host); exit(1); } memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr)); // memcpy() copie n octets // (n= sizeof(pingaddr.sin_addr)) depuis la zone mémoire src (src=h->h_addr) vers // la zone mémoire dest (dest=&pingaddr.sin_addr); ce qui veut dire qu'on prend le membre // h_addr de la struct hostent nommée h (qui vient d'être résolue par gethostbyname) pour // le placer à &pingaddr.sin_addr. hostname = h->h_name; printf("monip: h->h_name=%s (résolu par gethostbyname sur ce socket qui est pingsock)\n",hostname); // pkt = (struct icmp *) packet; // rappel, pkt pointe sur une structure icmp; // ici elle s'appelle packet. memset(pkt, 0, sizeof(packet)); pkt->icmp_type = ICMP_ECHO; // le membre icmp_type de la struct icmp // pointée par pkt est rempli par ICMP_ECHO pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet)); // le cksum est // rempli aussi. // c = sendto(pingsock, packet, sizeof(packet), 0, (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in)); // ssize_t sendto(int s, const void *buf, size_t len, int flags, // const struct sockaddr *to, socklen_t tolen); if(c < 0 || c != sizeof(packet)) { if(c < 0) perror("monip: sendto"); fprintf(stderr, "monip: write incomplete\n"); exit(1); } else { // alors par ici je peux essayer d'imprimer le paquet envoyé : if(imppkt(*pkt, "envoyé")==-1) { printf("monip: Problème d'impression du paquet.\n"); } else { addr=(unsigned int)pingaddr.sin_addr.s_addr; // le paquet a été envoyé là-bas. printf("monip: adresse dest.=%u\n", addr); // je la veux en IP pointée. // // long2ip printf("monip: long2ip(%u) => %s\n", addr, long2ip(addr) ); // if(!(h = gethostbyname(host))) { fprintf(stderr, "monip: unknown host %s\n", host); exit(1); } else { printf("monip: host de dest.=%s (le même h->h_name que résolu ci dessus)\n\n", h->h_name); } } } // signal(SIGALRM, noresp); alarm(5); // give the host 5000ms to respond // listen for replies while (1) { struct sockaddr_in from; size_t fromlen = sizeof(from); // //ssize_t recvfrom(int s, void *buf, size_t len, int flags, // struct sockaddr *from, socklen_t *fromlen); printf( "monip: avant recvfrom\n"); if((c = recvfrom(pingsock, packet, sizeof(packet), 0, (struct sockaddr *) &from, &fromlen)) < 0) { if(errno == EINTR) continue; perror("monip: recvfrom"); continue; } // close(pingsock); // je n'ai plus besoin de ça. printf( "monip: Ok après recvfrom\n"); // if(c >= 76) { // ip + icmp struct iphdr *iphdr = (struct iphdr *) packet; // pkt = (struct icmp *) (packet + (iphdr->ihl << 2)); // skip ip hdr if(pkt->icmp_type == ICMP_ECHOREPLY) { printf("monip: %s is alive !\n", hostname); if(imppkt(*pkt, "reçu")==-1) { printf("monip: Problème d'impression du paquet.\n"); } else { // l'impression du paquet revenu est Ok addr=from.sin_addr.s_addr; // from est une struct sockaddr_in, // dont un membre nommé sin_addr est une struct in_addr, // dont le seul membre est s_addr. printf("monip: adresse source=%u\n", addr); // // long2ip printf( "long2ip(%u) => %s\n", addr, long2ip(addr) ); // // pour l'instant, AF_INET qui est le type vaut 2 if((hh=gethostbyaddr(&addr, sizeof(addr), 2))==NULL) { // struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type); perror("monip: gethostbyaddr()"); printf("monip: gethostbyaddr() pas Ok\n\n"); } else { // gethostbyaddr a créé une struct hostent qui s'appeller hh hostname = hh->h_name; printf("monip: host de source du retour=%s (hh->h_name)\n", hostname); printf("monip: gethostbyaddr() Ok\n\n"); printf("monip: adresse src du retour=%s\n", long2ip(iphdr->saddr)); // IP pointée. // printf("monip: adresse dst du retour=%s\n", long2ip(iphdr->daddr)); // IP pointée. printf("monip: adr. dst nr du retour=%s\n\n", long2ipnr(iphdr->daddr)); // IP pntnr. // pmonIP=long2ipnr(iphdr->daddr); // } // c'est donc ici la fin du else } break; } // } // } return pmonIP; // } // // pour voir si le port 23 attend du monde : // nmap 127.0.0.1 -p 23 // // pour voir ce que le client et le serveur se disent : (là ça cause, 1 ou 2 paquets +/- lisibles avec le -A) // sudo tcpdump -vvvAXXti ppp0 -s 0 tcp port 23 // sudo tcpdump -vvvAXXi ppp0 -s 0 (tous les paquets avec timestamp) // sudo tcpdump -vvvAXXti ppp0 -s 0 (tous les paquets mais sans timestamp) // //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// static int Stn(char* paddrIP) { unsigned int addrIPnr, *paddrIPnr; unsigned int v; printf("Stn: là, monIP=%s (=%u en %%u)\n\n",paddrIP,ip2long(paddrIP)); SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); // ici sock est une socket en stream char command[BUF_SIZE]; char line[LIN_SIZE]; unsigned char *buffer_RX,*buffer_TX; int connection, etat, flag_nego_option, i, nb_lu, nb_ec, ntour=0, var_etat, verif_select, selectold=0; struct sockaddr_in sin; struct termios term_initial; struct timeval delai; fd_set rd, wr, er; // creation d'un socket avec l'adresse que je construis ici : // pour l'instant il faut ma propre sin_addr; c'est une struct in_addr, sin.sin_addr.s_addr = htonl(ip2long(paddrIP)); // dont le seul membre est s_addr... ZZZ nr avec le htonl // // (de type in_addr_t) sin.sin_port = htons(PORT); // PORT=23 pour telnet. sin.sin_family = AF_INET; // pour l'instant, AF_INET qui est le type vaut 2 printf("Stn: Contrôles :\n"); // printf("Stn: sin.sin_addr=%u\n",sin.sin_addr); // c'est une sin_addr mais il affiche printf("Stn: sin.sin_port=%d\n",ntohs(sin.sin_port)); // son membre s_addr en unsigned printf("Stn: sin.sin_family=%d\n",AF_INET); printf("Stn: sin.sin_addr.s_addr=%u, (=%s) (nr)\n\n",sin.sin_addr.s_addr, // long dans l'ordre réseau long2ip(sin.sin_addr.s_addr)); printf("Stn: try to connect :\n"); // /*Connection au point distant avec 30 secs de delai max*/ etat=-1; connection=-1; while(connection!=0) { if((connection=connect(sock,(SOCKADDR *) &sin, sizeof(SOCKADDR))) == SOCKET_ERROR) { perror("Stn: connect()"); exit(errno); } else printf("Stn: connect() Ok, connexion=%d\n",connection); // // printf("Stn: try to log in, now : (CRLF=\"%s\")\n",CRLF); // printf("Stn: try to log in, now :\n"); if (errno==EINPROGRESS&&etat!=1) printf("\nDemande de connection Changement de var_etat=%d\n",etat=1); if (errno==EALREADY&&etat!=2) printf("\nDemande de connection en cours connect=%d valeur de errno %d %s de etat=%d", connection, errno, strerror(errno), etat=2); if(errno==234) { var_etat=alarm(0); printf("\nconnection OK=%d valeur etat %d",connection=0,etat=3); } if(connection==0&&etat!=3) { var_etat=alarm(0); printf("Stn: connection=%d OK valeur du timeout %d\n",connection,ETIMEDOUT); } } /*fin de Connection au point distant*/ // MSG_DE_NEGO(sock); // /* on entre dans la boucle de communication */ while(connection == 0) { //DVA: c'est-à-d. tant que la connexion est Ok, car elle vaut 0 quand Ok. /*Initialisation de l'ensemble des descripteurs a multiplexer*/ FD_ZERO(&rd); FD_ZERO(&wr); FD_SET(sock, &rd); FD_SET(sock, &wr); FD_SET(0, &rd); FD_SET(0, &wr); // ça, il le faut pour multiplexer le sock et stdin-0. // printf("DVA: FD_ISSET(sock, &rd)=%d\n",FD_ISSET(sock, &rd)); // printf("DVA: FD_ISSET(0, &rd)=%d\n",FD_ISSET(0, &rd)); // printf("DVA: FD_ISSET(sock, &wr)=%d\n",FD_ISSET(sock, &wr)); // printf("DVA: FD_ISSET(0, &wr)=%d\n",FD_ISSET(0, &wr)); ntour++; /* Selection de l'ensemble des descripteurs a multiplexer en reception */ if(select(sock+1,&rd,&wr,NULL,&delai) != selectold) { printf("DVA: ntour=%d\n",ntour); printf("DVA: select(sock+1,&rd,&wr,NULL,&delai)=%d\n",select(sock+1,&rd,&wr,NULL,&delai)); selectold=select(sock+1,&rd,&wr,NULL,&delai); } if((verif_select=select(sock+1,&rd,&wr,NULL,&delai))<0) { printf("DVA: select->errno=%d\n",errno); perror("select()"); break; } if(verif_select>=3) printf("valeur de verif_select = % d",verif_select); if(FD_ISSET(0,&rd)) { /*Debut du if de lecture sur le 0 */ /*Initialisation d un bloc memoire pour un caractere*/ if((buffer_RX=(char*) calloc (LG_BUFFER,sizeof (char)))==NULL) printf("\nImpossible d'allouer la memoire buffer_RX 0"); else memset(buffer_RX,NULL,sizeof (char)); /*printf("\ninitialisation du buffer_RX %d",*buffer_RX);*/ nb_lu=0; if((nb_lu=read(0,buffer_RX,LG_BUFFER))<0) printf("\nerreur sur lecture d'entree ou rien a ecrire retour de nb_lu %d",nb_lu); if(nb_ec=write(sock,buffer_RX,nb_lu)) printf ("\nun caractere ecrit sur socket %d",*buffer_RX); free(buffer_RX); } /* Fin du if de lecture sur le 0 */ if(FD_ISSET(sock,&rd)) { /* Debut du if de lecture sur le sock */ if((buffer_RX=(unsigned char*) calloc (LG_BUFFER,sizeof (unsigned char)))==NULL) printf("\nImpossible d'allouer la memoire buffer_RX pour sock"); nb_lu=0; i=0; // ssize_t recv(int s, void *buf, size_t len, int flags); //DVA: j'ajoute un flag=0 while((nb_lu=recv(sock,buffer_RX,LG_BUFFER,0))>=0) { /*Debut du while*/ if(nb_lu==0) printf("\nValeur de connection = %d connection fermee par le distant",connection=1); if(buffer_RX[0]==255) // 255=IAC { /*Un caractere IAC est arrive*/ i=1; flag_nego_option=1; /**mess_nego=*buffer_RX;*/ while(flag_nego_option==1) {/*debut du while*/ /*printf ("\nvaleur de i=%d",i);*/ if((buffer_RX=realloc(buffer_RX,(i+1)*sizeof(unsigned char)))==NULL) printf("\nErreur sur attribution memoire"); nb_lu=read(sock,buffer_RX+i,LG_BUFFER); if(*(buffer_RX+i)>=236 && *(buffer_RX+i)<255) { /*Phase de test 250>IAC<255*/ ++i; if((buffer_RX=realloc(buffer_RX,(i+1)*sizeof(unsigned char)))==NULL) printf("\nErreur sur attribution memoire"); nb_lu=read(sock,buffer_RX+i,LG_BUFFER); if(buffer_RX[i-1]==250) { /*detection de SB*/ do { /*lecture jusqu'a SE*/ ++i; if((buffer_RX=realloc(buffer_RX,(i+1)*sizeof(unsigned char)))==NULL) printf("\nErreur sur attribution memoire"); nb_lu=read(sock,buffer_RX+i,LG_BUFFER); } while(buffer_RX[i]!=240); } *(buffer_RX+(i+1))=0; NEGOCIATION(buffer_RX,sock,i); } flag_nego_option=0; free(buffer_RX); /*printf("\nle free(mes_nego) est ok valeur de l'adresse mess_nego %d %d\n",mess_nego,*mess_nego);*/ memset(buffer_RX,0,strlen(buffer_RX)); ++i; } /*fin de while(flag_nego_option)*/ /*printf("\nfin du if(buffer_RX[0]==255)");*/ // 255=IAC } /*fin de if(buffer_RX[0]==255)*/ // 255=IAC else { /*Debut du else*/ write(stdout, buffer_RX, nb_lu); } /*Fin du else*/ nb_lu=0; } /*fin du while((nb_lu=recv(sock,buffer_RX,LG_BUFFER))>0)*/ free(buffer_RX); memset(buffer_RX, 0, strlen(buffer_RX)); } /* Fin du if de lecture sur le sock */ } /* Fin du while connection*/ printf("\nSortie de boucle sans raison nb_lu = %d",nb_lu); close(sock); // if((tcsetattr(0,TCSANOW,&term_initial))!=0) printf("\nremise en etat du 0 echoue\n"); printf ("\nSortie du prog\n"); // printf("Stn: invite de login :\n"); read_server(sock, line); // lecture de l'invite de login puts(line); // affichage de celle ci printf("Stn: envoi de %s+\"%s\"\n\n", "guest", "CRLF"); sprintf(command, "%s%s", "guest", CRLF); write_server(sock, command); // printf("Stn: invite de password :\n"); read_server(sock, line); // lecture de l'invite de password puts(line); // affichage de celle ci printf("Stn: envoi de %s+\"%s\"\n", "guest1", "CRLF"); sprintf(command, "%s%s", "guest1", CRLF); write_server(sock, command); // read_server(sock, line); puts(line); // printf("Stn: end of trial.\n"); // on n'arrive pas encore ici, tu rêves ??? return 0; } // // int main(int argc, char **argv) ///////////////////////////////////////// { //DVA: argc--; argv++; char* paddrIP; paddrIP=monip(argc, *argv); //////////////////////////////////////////////// printf("mtn: monIP=%s\n",paddrIP); printf("mtn: ici\n\n"); int a=Stn(paddrIP); //////////////////////////////////////////////////////// exit(1); } // // fin.
arg' encore un pavé :aie: