Hace algo así como un añito os comentaba que mi página web (no ésta, sino la que tengo para mis frikadas MSXeras) no cumplía los estándares del W3C, y ponía como excusa que es que la había hecho a mano y bla bla.
Pues bien, recientemente y a raíz del escándalo de la nueva web del congreso español, he recordado el tema. Una de las críticas se basa en el hecho de que dicha web no valida el más mínimo estándar. Al leer dichos algos, me he sentido aludido y he sentido un pelín de vergüenza por pecar mi propio sitio del mismo delito webístico.
Así que me he puesto manos a la obra, y he rehecho mi página web dedicada al MSX de forma que ahora cumple los estándares XHTML y CSS (lo cual me ha supuesto aprender algo de las susodichas tecnologías, de las que no tenía ni idea). Ahora sí puedo ir por la calle con la cabeza bien alta y gritar "¡Soy estándar!", a lo que probablemente los transeuntes responderán "No te acerques hijo, que está loco", pero bueno, son gajes del oficio.
Nota: La hoja de estilos da rabia de lo simple que es. Si algún webgurú se aburre mucho y se atreve a mejorarla, a lo mejor hasta incluso la uso y pongo su nombre en mi web (qué generoso soy).
29 junio 2007
25 junio 2007
Ríase usted de Kafka
Allá por el segundo lustro de los años 90, yo era un lozano jovenzuelo dedicado a la adquisición infatigable de conocimientos universitarios. Ello me proporcionaba, en épocas veraniegas y vacacionales en general, largos períodos de asueto que a menudo incluían largas sesiones de meditación y/o divertimento informático en mi casa.
Muchas de mis amistades se encontraban en similar situación, por lo que no era infrecuente que acabáramos reunidos en casa de alguno de nosotros filosofando sobre el origen del universo, haciendo fanzines sobre maquinitas obsoletas, jugando al Salamander a dobles, o todo ello a la vez; y divertimentos similares.
Pues bien, dos de estos amigotes tienen un talento especial para la plasmación gráfica de entidades abstractas (uséase para el dibujo), y era habitual que estando en mis aposentos me pidieran papel y hoja (no, no lo he escrito mal; es una historia muy larga) a fin de realizar en tiempo real un volcado en papel de un repentino arrebato de creatividad. Estos dos individuos no son otros que el putoso al que ya conoceis, y el señor Yombo, el cual no sé si quiere salir afoteado aquí pero como pista os diré que es hermano de Marce.
Por suerte, tuve la feliz idea de guardar tamañas obras de arte, y afortunadamente muchas de ellas han sobrevivido hasta nuestros días. Hete aquí una pequeña selección de las mismas, que tuve a bien escanear un día que a Kaito aún no le había dado por nacer. Eso sí, he de advertiros de la crudeza creativa de las mismas; no me responsabilizo de las posibles pesadillas que podais tener como consecuencia de la vislumbración de las mismas.
Nota: No olvideis hacer cataclack en las imágenes para verlas más grandotas, que si no, no tiene gracia.
Nota bonus: ¡Encuentra el infiltrado! Una de las obras de arte no está hecha por el putoso ni por el Yombo, ¿eres capaz de decir cuál es la obra en cuestión y cuál es el autor de la misma?
Esta cosa estuvo colgada en mi habitación años enteros, e iba siendo actualizada periódicamente por el artista. El "arte" está censurado porque es un número telefónico real.
Muchas de mis amistades se encontraban en similar situación, por lo que no era infrecuente que acabáramos reunidos en casa de alguno de nosotros filosofando sobre el origen del universo, haciendo fanzines sobre maquinitas obsoletas, jugando al Salamander a dobles, o todo ello a la vez; y divertimentos similares.
Pues bien, dos de estos amigotes tienen un talento especial para la plasmación gráfica de entidades abstractas (uséase para el dibujo), y era habitual que estando en mis aposentos me pidieran papel y hoja (no, no lo he escrito mal; es una historia muy larga) a fin de realizar en tiempo real un volcado en papel de un repentino arrebato de creatividad. Estos dos individuos no son otros que el putoso al que ya conoceis, y el señor Yombo, el cual no sé si quiere salir afoteado aquí pero como pista os diré que es hermano de Marce.
Por suerte, tuve la feliz idea de guardar tamañas obras de arte, y afortunadamente muchas de ellas han sobrevivido hasta nuestros días. Hete aquí una pequeña selección de las mismas, que tuve a bien escanear un día que a Kaito aún no le había dado por nacer. Eso sí, he de advertiros de la crudeza creativa de las mismas; no me responsabilizo de las posibles pesadillas que podais tener como consecuencia de la vislumbración de las mismas.
Nota: No olvideis hacer cataclack en las imágenes para verlas más grandotas, que si no, no tiene gracia.
Nota bonus: ¡Encuentra el infiltrado! Una de las obras de arte no está hecha por el putoso ni por el Yombo, ¿eres capaz de decir cuál es la obra en cuestión y cuál es el autor de la misma?
Esta cosa estuvo colgada en mi habitación años enteros, e iba siendo actualizada periódicamente por el artista. El "arte" está censurado porque es un número telefónico real.20 junio 2007
¡Cumpleaño!
Hace mucho tiempo, en una galaxia muy lejana...
- *BIP* Informe del agente K4-1-t0. Acabo de llegar al planeta Tierra. Procediendo al estudio de la morfología planetaria en vistas a una posible invasión.
- ¡Cariño, mira qué cosita más mona he encontrado! ¿Nos lo podemos quedar?
- Pero... oiga, señora... se confunde usted...
- Caramba, su densidad capilar es muy similar a la mía... pues sí, nos lo quedamos.
- ¡AAAAH! ¡Socorro! ¡A mí la brigada intergaláctica de rescate!
De esta prometedora forma comenzó la andadura de nuestro héroe Kaito en el planeta Tierra, hace ahora exactamente un año.
Tal evento no podía pasar desapercibido en el entorno familio-amistoidal del susodicho heredero al liderazgo social, y como era menester, fastuosas fueron las celebraciones correspondientes.
- Gracias, querida familia... aunque a mi edad, uno ya va p'abajo y pocas ganas de celebración quedan...
No obstante, pasados los ágapes y las felicitaciones, subyace la dura realidad: ahora que es mayor, Kaito debe enfrentarse a la vida adulta, que no es precisamente un camino de rosas. Toca en primer lugar, buscar pareja para formar una familia:
- (regla número uno del ligoteo: aproximarse sigilosamente a la víctima, sin despertar sospechas...)
Tareas no menos duras son conseguir un trabajo y una vivienda digna, y es que la vida está muy difícil.
- Mis papis ya empiezan a mirarme raro... voy a tener que buscarme un curro y un pisito, buf... vamos a ver, "se necesita babeador con experiencia en mordiscos a traición"...
- "Si se le desinfla la casa, sople por el tubito"... a mí, la verdad, no me parece muy normal esto...
Moraleja: Kaito ya sabe que no puede uno fiarse de los políticos.
- *BIP* Informe del agente K4-1-t0. Acabo de llegar al planeta Tierra. Procediendo al estudio de la morfología planetaria en vistas a una posible invasión.
- ¡Cariño, mira qué cosita más mona he encontrado! ¿Nos lo podemos quedar?- Pero... oiga, señora... se confunde usted...
- Caramba, su densidad capilar es muy similar a la mía... pues sí, nos lo quedamos.- ¡AAAAH! ¡Socorro! ¡A mí la brigada intergaláctica de rescate!
De esta prometedora forma comenzó la andadura de nuestro héroe Kaito en el planeta Tierra, hace ahora exactamente un año.
Tal evento no podía pasar desapercibido en el entorno familio-amistoidal del susodicho heredero al liderazgo social, y como era menester, fastuosas fueron las celebraciones correspondientes.
- Gracias, querida familia... aunque a mi edad, uno ya va p'abajo y pocas ganas de celebración quedan...No obstante, pasados los ágapes y las felicitaciones, subyace la dura realidad: ahora que es mayor, Kaito debe enfrentarse a la vida adulta, que no es precisamente un camino de rosas. Toca en primer lugar, buscar pareja para formar una familia:
- (regla número uno del ligoteo: aproximarse sigilosamente a la víctima, sin despertar sospechas...)Tareas no menos duras son conseguir un trabajo y una vivienda digna, y es que la vida está muy difícil.
- Mis papis ya empiezan a mirarme raro... voy a tener que buscarme un curro y un pisito, buf... vamos a ver, "se necesita babeador con experiencia en mordiscos a traición"...
- "Si se le desinfla la casa, sople por el tubito"... a mí, la verdad, no me parece muy normal esto...Moraleja: Kaito ya sabe que no puede uno fiarse de los políticos.
31 mayo 2007
Estantería REALMENTE fabulosa
He aquí parte de un folleto propagandístico aparecido en el buzón de mi humilde morada ayer mismo. Se trata de una empresa armariera que por la compra de sus productos regala una estantería, según dicen, fabulosa:

Ya lo creo que es fabulosa, teniendo en cuenta que mide veinte metros de alto por cinco de ancho por tres de fondo. Se me antoja realmente un buen negocio, pues con semejante monstruo en mi poder, las posibilidades son infinitas, pudiendo por ejemplo:
En fin, curioso lo que puede uno encontrar por esos mundos de Yupi.
Ya lo creo que es fabulosa, teniendo en cuenta que mide veinte metros de alto por cinco de ancho por tres de fondo. Se me antoja realmente un buen negocio, pues con semejante monstruo en mi poder, las posibilidades son infinitas, pudiendo por ejemplo:
- Alquilar las baldas como plazas de parking.
- Montar un hotel cápsula al más puro estilo nipón (a cuatro cápsulas por balda).
- Vender mi piso y vivir en el susodicho armario (¡seis habitaciones de 15 m2 cada una!)
En fin, curioso lo que puede uno encontrar por esos mundos de Yupi.
25 mayo 2007
Mi orgullo friki (extracto)
;================================================
;=== Proceso del paquete recibido: ===
;=== Comprobacion del protocolo del paquete ===
;================================================
ld hl,(IN_BUFFER+2) ;Ether-Type
;--- Comprueba si el protocolo es conocido,
; si lo es salta a la parte adecuada del codigo
ld de,#0008
call COMP
jp z,IS_IP
ld de,#0608
call COMP
jp z,IS_ARP
;--- Protocolo desconocido: lo ignoramos
jp END_GET_PACK
;==============================
;=== Paquete ARP recibido ===
;==============================
;Algoritmo segun RFC826, "Packet Reception"
IS_ARP: ;--- Comprueba el hardware y el protocolo
ld hl,(IN_BUFFER+4)
ld de,#0100
call COMP
jp nz,END_GET_PACK
ld hl,(IN_BUFFER+6)
ld de,#0008
call COMP
jp nz,END_GET_PACK
;--- Comprueba si el tamanyo de la dir HW es 0: paquete UNARP.
; En ese caso busca la entrada y la borra si no es estatica.
ld a,(IN_BUFFER+8)
cp 6
jr z,NO_UNARP
or a
jp nz,END_GET_PACK ;Si no es 0 ni 6, es incorrecto
ld de,IN_BUFFER+18 ;Busca entrada ARP...
call SRCH_ARP
jp c,END_GET_PACK
ld a,(ix)
cp 1
jp z,END_GET_PACK
ld (ix),0 ;...y si la encuentra, la borra
call END_GET_PACK ;si no es estatica.
NO_UNARP:
;--- Si la IP de origen es 0, no cachea la direccion
; (clientes DHCP comprobando la direccion que se
; les acaba de asignar pueden enviar un ARP request
; con la IP del enviador a cero)
ld a,#FF
ld (MERGE_FLAG),a
ld hl,IN_BUFFER+18
ld de,ZERO32
call COMP32
jr z,IS_ARP_2
;--- Comprueba si hay una entrada ARP para esa IP
xor a
ld (MERGE_FLAG),a
ld de,IN_BUFFER+18
call SRCH_ARP
jr c,NOTINCACHE
;* Encontrada: actualiza dir MAC
ld a,#FF
ld (MERGE_FLAG),a
ld a,(ix) ;Si es estatica, no hace nada
cp 1
jp z,NOUPTIMER
push ix
pop de
inc de
ld hl,IN_BUFFER+12
ld bc,6
ldir
NOUPTIMER:
;* Actualiza temporizador de expiracion
ld (ix),2 ;Por si estaba en resolucion
push ix
pop hl
ld bc,11
add hl,bc
ex de,hl
ld hl,ARP_TOUT
ld bc,4
ldir
NOTARPSTAT:
NOTINCACHE:
;--- Si la IP requerida no es la nuestra, terminar ya
IS_ARP_2: ld hl,IN_BUFFER+28
ld de,BUF_IPLOCAL
call COMP32
jp nz,END_GET_PACK
;--- Si la entrada no estaba en la tabla, anyadirla
ld a,(MERGE_FLAG)
or a
jr nz,OKMERGEARP
call GET_FREE_ARP
ld (ix),2 ;Entrada dinamica
push ix ;Copia la MAC y la IP de una sentada
pop de
inc de
ld hl,IN_BUFFER+12
ld bc,10
ldir
ld hl,ARP_TOUT ;Establece temp. de expiracion
ld bc,4
ldir
OKMERGEARP:
;--- Si el paquete era Request, enviar Reply
ld a,(IN_BUFFER+11)
cp 1
call z,SEND_ARP_RP
jp END_GET_PACK
MERGE_FLAG: db 0
;===============================
;=== Datagrama IP recibido ===
;===============================
IS_IP: ;
;--- Primero comprobamos que llegue al tamanyo minimo:
; Eth1 Eth2 Type Cabecera(20)
ld hl,(INBUF_SIZE)
ld de,34
call COMP
jp nc,END_GET_PACK
;--- Guardamos el tamanyo de la cabecera IP en OUT_BUFFER.
; Si es <20 bytes, ignoramos el paquete.
ld a,(IN_BUFFER+4)
and #0F
cp 5
jp c,END_GET_PACK
sla a
sla a
ld l,a
ld h,0
ld (IP_HEADER_LEN),hl
;--- Guardamos el tamanyo total del paquete en OUT_BUFFER+2.
; Si es >576 bytes, ignoramos el paquete.
ld a,(IN_BUFFER+6)
ld h,a
ld a,(IN_BUFFER+7)
ld l,a
ld de,577
call COMP
jp c,END_GET_PACK
ld (IP_TOTAL_LEN),hl
;--- Calcula el checksum de la cabecera
ld a,(CHKVECT)
and %10
jr z,IPCHKSOK
ld ix,IN_BUFFER+4
ld bc,(IP_HEADER_LEN)
call CALC_CHKSUM
ld a,d
or e
jp nz,END_GET_PACK
IPCHKSOK: ;
;--- Comprueba la direccion IP de destino,
; debe ser la nuestra o una de broadcast
;* Es nuestra IP?
ld hl,IN_BUFFER+20
ld de,BUF_IPLOCAL
call COMP32
jr z,OK_IPDEST
;* Es de broadcast? (Mascara OR dir = todo 1s?)
ld hl,SUBNET_MASK
ld de,IN_BUFFER+20
ld b,4
CHKIPBROAD2: ld a,(de)
or (hl)
inc a
jp nz,END_GET_PACK
inc hl
inc de
djnz CHKIPBROAD2
OK_IPDEST:
;--- Si el campo de version no tiene 4, ignoramos el datagrama
ld a,(IN_BUFFER+4)
and #F0
cp #40
jp nz,END_GET_PACK
;--- Si es un fragmento de datagrama, lo ignoramos
ld hl,(IN_BUFFER+10)
res 7,l ;Pone a 0 el bit no usado (previene futuras extensiones de IP)
res 6,l ;Pone a 0 el bit DF. Desde ahora HL solo tiene DF y Frag. Off.
ld a,h ;Si MF o Fragment Offset son <>0,
or l ;es un fragmento: ignorarlo
jp nz,END_GET_PACK
;--- Si el paquete contiene opciones, las descartamos
; (movemos los datos a la posicion IN_BUFFER+24)
ld hl,(IP_HEADER_LEN) ;HL = Long cabecera
ld de,20
call COMP
jr z,IPOPTOK
ld bc,IN_BUFFER+4
add hl,bc ;HL = Inicio de los datos
ld de,IN_BUFFER+24
ld bc,(IP_TOTAL_LEN)
ldir
ld hl,(IP_TOTAL_LEN) ;Cambia el tamanyo
ld de,(IP_HEADER_LEN) ;del paquete para no incluir
or a ;las opciones IP
sbc hl,de ;HL = Long. sin cabeceras
ld de,20
add hl,de ;HL = Long. con cabecera sin opciones
ld a,h
ld (IN_BUFFER+6),a
ld a,l
ld (IN_BUFFER+7),a
ld (IP_TOTAL_LEN),hl
ld (IP_HEADER_LEN),de
IPOPTOK:
;--- Sustituye el campo de tamanyo total del paquete
; por el tamanyo de los datos, y en little-endian
ld hl,(IP_TOTAL_LEN)
ld de,(IP_HEADER_LEN)
or a
sbc hl,de
ld (IN_BUFFER+6),hl
;--- Decide accion segun protocolo transportado
ld a,(IN_BUFFER+13)
cp 6
jp z,IS_TCP
cp 17
jp z,IS_UDP
cp 1
jp z,IS_ICMP
jp END_GET_PACK ;Desconocido: ignoramos
;===============================
;=== Mensaje ICMP recibido ===
;===============================
IS_ICMP: ;--- Comprueba el checksum
ld a,(CHKVECT)
and %10000
jr z,ICMPCHK_OK
ld ix,IN_BUFFER+24
ld bc,(IN_BUFFER+6)
call CALC_CHKSUM
ld a,d
or e
jp nz,END_GET_PACK
ICMPCHK_OK: ;
;--- Comprobamos el tipo
ld a,(IN_BUFFER+24)
or a ;ECHO Reply?
jr z,IS_ICMP_EREP
cp 3
jp z,IS_ICMP_HOSTUN
cp 8 ;ECHO request?
jp nz,END_GET_PACK ;Otro: lo ignoramos
;--- ICMP Echo Request: Lo respondemos si REPLYECHO<>0
IS_ICMP_EREQ: ld a,(REPLYECHO)
or a
jp z,END_GET_PACK
ld hl,IN_BUFFER+24 ;Copiamos el mensaje tal cual en la respuesta
ld de,OUT_BUFFER+24
ld bc,(IN_BUFFER+6)
push bc
inc bc ;Para que incluya el 0 de padding
ldir
xor a
ld (OUT_BUFFER+24),a ;Cambia el tipo a "Echo reply"
pop bc
ld hl,0
ld (OUT_BUFFER+26),hl ;Borra checksum antiguo
ld ix,OUT_BUFFER+24
call CALC_CHKSUM
ld (OUT_BUFFER+26),de ;Establece nuevo checksum
ld hl,(IN_BUFFER+16) ;IP destino = el originador del mensaje
ld de,(IN_BUFFER+18)
ld bc,(IN_BUFFER+6) ;Longitud
ld a,1 ;Protocolo = ICMP
jp SEND_IP
;--- ICMP Echo Reply: lo encolamos si no hay ya 4 encolados
IS_ICMP_EREP: ld a,(ICMPI_PINDEX)
ld b,a
inc b
ld ix,ICMPI_IP0-11
ld de,11
BUC_EREP1: add ix,de
djnz BUC_EREP1 ;Ahora IX apunta a la zona de datos adecuada
ld a,(ICMPI_PINDEX)
ld b,a
ld a,(ICMPI_GINDEX)
cp b
jr nz,EREP_HAYSITIO
ld a,(ix) ;Indice GET = Indice PUT:
or (ix+1) ;Hay sitio si entrada vacia (IP=0),
or (ix+2) ;si no, terminamos.
or (ix+3)
jp nz,END_GET_PACK
EREP_HAYSITIO: ;
ld hl,(IN_BUFFER+16)
ld (ix),l
ld (ix+1),h
ld hl,(IN_BUFFER+18)
ld (ix+2),l
ld (ix+3),h
ld a,(IN_BUFFER+12) ;TTL
ld (ix+4),a
ld hl,(IN_BUFFER+28) ;Identificador (guardamos en L.E.)
ld (ix+5),h
ld (ix+6),l
ld hl,(IN_BUFFER+30) ;Numero de secuencia (guardamos en L.E.)
ld (ix+7),h
ld (ix+8),l
ld hl,(IN_BUFFER+6) ;Longitud de los datos
ld bc,8 ;Resta long. cabecera ICMP
or a
sbc hl,bc
ld (ix+9),l
ld (ix+10),h
ld a,(ICMPI_PINDEX) ;Incrementa indice PUT
inc a ;saltando de 3 a 0
and %111
ld (ICMPI_PINDEX),a
jp END_GET_PACK
;--- ICMP Destination Unreachable: si esta asociado a una
; conexion TCP, la abortamos con codigo 7
;Nota: la cabecera del paquete causante de esta respuesta
;ICMP esta en IN_BUFFER+32.
IS_ICMP_HOSTUN: ld a,(IN_BUFFER+9+32)
cp 6 ;Si el paquete causante no es TCP, ignorarlo
jp nz,END_GET_PACK
ld hl,(IN_BUFFER+20+28)
ld de,(IN_BUFFER+22+28)
ld a,(IN_BUFFER+24+28)
ld iyh,a
ld a,(IN_BUFFER+25+28)
ld iyl,a
ld a,(IN_BUFFER+26+28)
ld ixh,a
ld a,(IN_BUFFER+27+28)
ld ixl,a
call SEARCH_TCP
cp #FF ;Conexion asociada inexistente: terminar
jp z,END_GET_PACK
call LOAD_TCB
xor a ;Cierra la conexion con codigo 7
ld (TCP_STATE),a
ld a,7
ld (LAST_CLOSE),a
call SAVE_TCB
jp END_GET_PACK
;==============================
;=== Paquete UDP recibido ===
;==============================
IS_UDP: ;--- Comprueba checksum, excepto si CHKVECT dice lo contrario
ld a,(CHKVECT)
and %1000
jp z,OK_UDP_CHKSUM
;* Para calcular el checksum, componemos la pseudo-cabecera
; justo antes de los datos, pisando la cabecera IP.
; Pero como el orden de los datos (palabras de 16 bits)
; no es importante para el calculo,
; aprovechamos que las direcciones IP y el campo de protocolo
; ya estan establecidos en la cabecera IP, y asi
; solo necesitamos establecer 0 donde estaba el TTL y la longitud UDP
; donde estaba el checksum IP.
xor a
ld (IN_BUFFER+12),a ;Campo TTL
ld hl,(IN_BUFFER+28) ;Long. UDP en el campo checksum IP
ld (IN_BUFFER+14),hl
ld hl,(IN_BUFFER+6)
ld bc,12 ;Para que incluya pseudo-cabecera
add hl,bc
push hl
pop bc
ld ix,IN_BUFFER+12
call CALC_CHKSUM
ld a,d
or e
jp nz,END_GET_PACK
OK_UDP_CHKSUM: ;
;--- Checksum correcto: comprobamos si es una respuesta DNS
; o un paquete DHCP, en ese caso se salta al codigo
; de procesamiento adecuado
ld a,(IN_BUFFER+26)
ld h,a
ld a,(IN_BUFFER+27)
ld l,a
ld de,DNS_PORT
call COMP
jp z,IS_DNS
ld de,68
call COMP
jp z,IS_DHCP
;--- Comprobamos que se puede almacenar el paquete
ld hl,(IN_BUFFER+6) ;Paquete demasiado grande?
ld de,548+8+1
call COMP
jp c,END_GET_PACK
ld a,(UDPI_PINDEX)
ld b,a
inc b
ld ix,UDPI_IP0-10
ld de,10
BUC_UDP1: add ix,de
djnz BUC_UDP1 ;Ahora IX apunta a la zona de datos adecuada
ld a,(UDPI_PINDEX)
ld b,a
ld a,(UDPI_GINDEX)
cp b
jr nz,UDPI_HAYSITIO
ld a,(ix) ;Indice GET = Indice PUT:
or (ix+1) ;Hay sitio si entrada vacia (IP=0),
or (ix+2) ;si no, terminamos.
or (ix+3)
jp nz,END_GET_PACK
UDPI_HAYSITIO: ;
;--- Almacenamos paquete
ld hl,(IN_BUFFER+16) ;IP origen
ld (ix),l
ld (ix+1),h
ld hl,(IN_BUFFER+18)
ld (ix+2),l
ld (ix+3),h
ld hl,(IN_BUFFER+24) ;Puerto origen (little endian)
ld (ix+4),h
ld (ix+5),l
ld hl,(IN_BUFFER+26) ;Puerto destino (little endian)
ld (ix+6),h
ld (ix+7),l
ld hl,(IN_BUFFER+6) ;Longitud datos UDP
ld bc,8
or a
sbc hl,bc
ld (ix+8),l
ld (ix+9),h
ld a,h ;Copia la parte de datos
or l ;si no tiene long 0
jr z,OK_UDPIDATA
push hl
ld hl,UDP_BUFFERS-512
ld de,512
ld a,(UDPI_PINDEX)
inc a
ld b,a
UDPLEN_LOP1: add hl,de
djnz UDPLEN_LOP1
ex de,hl
ld hl,IN_BUFFER+32
pop bc
ldir
OK_UDPIDATA: ;
ld hl,UDPI_PINDEX
call INC_UDPINDEX ;Actualiza indice para el proximo paquete
jp END_GET_PACK
;==============================
;=== Paquete DNS recibido ===
;==============================
IS_DNS: ;--- Comprueba si hay una peticion en curso
; y si coincide el ID con el ultimo enviado,
; si no, descarta el paquete
ld a,(DNS_STAT_P)
cp 1
jp nz,END_GET_PACK
ld hl,(IN_BUFFER+32)
ld de,(ID_DNS)
call COMP
jp nz,END_GET_PACK
;--- Si la respuesta esta truncada, ponemos error 21
; a no ser que podamos reintentar con el DNS secundario.
ld a,(IN_BUFFER+34)
and %00000010
jr z,DNS_NOTRUNC
call DNS_USE_SEC
jp nc,END_GET_PACK
ld a,3
ld (DNS_STAT_P),a
ld a,21
ld (DNS_STAT_S),a
jp END_GET_PACK
DNS_NOTRUNC: ;
;--- Si la respuesta contenia algun error,
; lo establecemos, a no ser que podamos reintentar
; con el DNS secundario.
ld a,(IN_BUFFER+35)
and %00001111
jr z,DNS_NOERR
call DNS_USE_SEC
jp nc,END_GET_PACK
ld a,3
ld (DNS_STAT_P),a
ld a,(IN_BUFFER+35)
and %00001111
ld (DNS_STAT_S),a
jp END_GET_PACK
DNS_NOERR: ;
;--- La respuesta no contiene error.
; Comprobamos si contiene alguna respuesta valida.
ld ix,IN_BUFFER+32 ;Apunta al ppio del paquete DNS
ld h,(ix+6)
ld l,(ix+7)
ld (ANCOUNT),hl ;Numero de respuestas
ld h,(ix+8)
ld l,(ix+9)
ld (NSCOUNT),hl ;Numero de servidores autoritativos
ld h,(ix+10)
ld l,(ix+11)
ld (ARCOUNT),hl ;Numero de secciones adicionales
ld ix,IN_BUFFER+44 ;IX=Inicio de la pregunta
SKIPQ_LOOP: ld a,(ix) ;Se salta la pregunta
inc ix ;(campo QNAME)
or a ;comprobando si hay compresion
jr z,SKIPQ_LOOP3
bit 7,a
jr z,SKIPQ_LOOP
SKIPQ_LOOP2: inc ix ;Se salta QTYPE y QCLASS
SKIPQ_LOOP3: inc ix ;(mas el segundo byte del puntero
inc ix ;si es necesario)
inc ix
inc ix ;Ahora IX apunta a las respuestas
;* Comprobamos si se nos da directamente la respuesta
SCAN_FOR_AN: ld bc,(ANCOUNT)
ld a,b
or c
jr z,SCAN_FOR_NS
call SCAN_DNS_RR
or a
jr z,SCAN_FOR_NS
ld a,2 ;Si habia una respuesta valida,
ld (DNS_STAT_P),a ;ponemos status=2 y terminamos
xor a
ld (DNS_STAT_S),a
jp END_GET_PACK
;* Si no, comprobamos si hay IPs de otros servidores
; en "Authoritative" o en "Aditional"
SCAN_FOR_NS: ld bc,(NSCOUNT)
ld a,b
or c
jr z,SCANNS_FAILED ;Seccion NS vacia?
call SCAN_DNS_RR ;Busca IPs de servidores
or a ;en "authoritative"
jp nz,CHANGE_DNS_IP
ld bc,(ARCOUNT)
ld a,b
or c
jr z,SCANNS_FAILED ;Seccion AR vacia?
call SCAN_DNS_RR ;Busca IPs de servidores
or a ;en "additional"
jp nz,CHANGE_DNS_IP
SCANNS_FAILED: ld a,3 ;Si no hay nada en NS ni AR, error 20
ld (DNS_STAT_P),a
ld a,20
ld (DNS_STAT_S),a
jp END_GET_PACK
;* Se ha encontrado la IP de otro DNS:
; Repetimos la consulta usandola
CHANGE_DNS_IP: ld hl,DNS_RESULT
ld de,DNS_IP ;Establecemos nueva direccion
ld bc,4 ;del DNS a consultar
ldir
ld hl,(ID_DNS) ;Incrementamos identificador
inc hl
ld (ID_DNS),hl
ld a,3 ;Ponemos estado secundario a 3
ld (DNS_STAT_S),a
xor a ;Inicializamos reintentos
ld (DNS_RETRY),a
inc a
ld (DNS_TOUT),a ;Para que se reenvie inmediatamente
jp END_GET_PACK
;--- Esta subrutina examina la zona a la que apunta IX
; y busca un RR del tipo "Direccion IP".
; Si lo encuentra, pone la IP en DNS_REPLY
; y DNS_RESP_FLAG a #FF (que devuelve en A).
; Al final, IX apunta a la siguiente zona.
;
; Entrada: BC = Numero de RRs en la zona.
SCAN_DNS_RR: xor a
ld (DNS_RESP_FLAG),a
DNS_AN_LOOP: push bc
SKIPQ_LOOP4: ld a,(ix) ;Se salta el nombre
inc ix ;comprobando si esta comprimido
or a
jr z,SKIPQ_LOOP6
bit 7,a
jr z,SKIPQ_LOOP4
SKIPQ_LOOP5: inc ix
SKIPQ_LOOP6: ;
ld a,(DNS_RESP_FLAG) ;Si ya hay una respuesta
or a ;valida, simplemente se salta
jr nz,DNS_AN_LOOP2 ;el RR
;* Comprueba que el tipo sea "Direccion IP"
ld h,(ix) ;IX apunta a TYPE
ld l,(ix+1)
ld de,1
call COMP
jr nz,DNS_AN_LOOP2
;* Se ha encontrado respuesta:
; se copia a DNS_RESULT
ld l,(ix+10)
ld h,(ix+11)
ld e,(ix+12)
ld d,(ix+13)
ld (DNS_RESULT),hl
ld (DNS_RESULT+2),de
ld a,#FF
ld (DNS_RESP_FLAG),a
;* Pasa al siguiente RR
DNS_AN_LOOP2: ld bc,10
add ix,bc ;Para que apunte a RDATA
ld b,(ix-2)
ld c,(ix-1) ;BC = RDLENGTH
add ix,bc
;* Si quedan RRs, vuelve a empezar
pop bc
dec bc
ld a,b
or c
jr nz,DNS_AN_LOOP
ld a,(DNS_RESP_FLAG)
ret
DNS_RESP_FLAG: db 0 ;#FF cuando se encuentra respuesta
;--- Esta subrutina es llamada cuando se recibe un paquete
; DNS erroneo o se consumen todos los reenvios.
; Lo que hace es comprobar si el DNS
; usado era el primario y hay un secundario disponible.
; Si es asi, establece DNS_IP con la direccion
; del DNS secundario, pone DNS_STAT_S a 2
; y DNS_RETRY a 0 (es decir, lo prepara todo
; para repetir la consulta usando el DNS secundario),
; y devuelve Cy=0.
; En caso contrario, devuelve Cy=1 (error).
DNS_USE_SEC: ld a,(DNS_STAT_S)
cp 1
scf
ret nz ;Si no era el primario
ld ix,BUF_IPDNS1
ld a,(ix+4)
or (ix+5)
or (ix+6)
or (ix+7)
scf
ret z ;Si era el primario pero no hay sec.
ld hl,BUF_IPDNS2 ;Establece secundario
ld de,DNS_IP ;y reinicia contador de
ld bc,4 ;reenvios
ldir
ld a,2
ld (DNS_STAT_S),a
xor a ;De paso pone Cy=0
ld (DNS_RETRY),a
inc a
ld (DNS_TOUT),a ;Para que se repita el envio inmediatamente
ret
;===============================
;=== Paquete DHCP recibido ===
;===============================
IS_DHCP: ld a,(DHCP_VECT) ;Ignorar si no usamos DHCP
or a
jp z,END_GET_PACK
ld a,(DHCP_STATE)
cp CONFIGURED
jp z,END_GET_PACK
;--- Obtiene el tipo del paquete
ld a,(IN_BUFFER+32) ;Es BOOTREPLY?
cp 2
jp nz,END_GET_PACK
ld hl,IN_BUFFER+36 ;El 'xid' coincide?
ld de,DHCP_XID
call COMP32
jp nz,END_GET_PACK
call DHCP_GET_TYPE
cp DHCPOFFER
jr z,IS_DHCP_OFFER
cp DHCPACK
jr z,IS_DHCP_ACK
cp DHCPNAK
jp z,IS_DHCP_NAK
jp END_GET_PACK ;Otros tipos son ignorados
;--- Paquete DHCPOFFER
IS_DHCP_OFFER:
;* Si el estado no es SELECTING, ignorarlo
ld a,(DHCP_STATE)
cp SELECTING
jp nz,END_GET_PACK
;* Guarda el identificador del servidor
call DHCP_GET_SERVER
jp c,END_GET_PACK
ld de,DHCP_SERVER
ld bc,4
ldir
;* Guarda el campo 'yiaddr' como la IP ofrecida
ld hl,IN_BUFFER+48
ld de,DHCP_YIADDR
ld bc,4
ldir
;* Guarda el 'xid' recibido
ld hl,IN_BUFFER+36
ld de,DHCP_RCVXID
ld bc,4
ldir
;* Pasa a estado REQUESTING y envia DHCPREQUEST
ld a,REQUESTING
ld (DHCP_STATE),a
ld a,DHCPREQUEST
call SEND_DHCP
call DHCP_FIRST
jp END_GET_PACK
;--- Paquete ACK
IS_DHCP_ACK:
;* Si el estado no es REBINDING, REQUESTING, RENEWING
; o INFORMING, ignorarlo
ISDHCPACK2: cp REQUESTING
jr z,ISDHCPACK3
cp RENEWING
jr z,ISDHCPACK3
cp REBINDING
jr z,ISDHCPACK3
cp INFORMING
jp nz,END_GET_PACK
ISDHCPACK3:
;* Si el identificador del servidor no coincide con el anterior,
; ignorar el mensaje
; (Problema: Que pasa si el ACK ha sido recibido en estado REBINDING,
; por un servidor distinto al usado anteriormente?
; Por eso, nos fiaremos unicamente del XID)
;call DHCP_GET_SERVER
;jp c,END_GET_PACK
;ld de,DHCP_SERVER
;call COMP32
;jp nz,END_GET_PACK
;* Inicializa los campos Lease, T1 y T2
ld hl,DHCP_T1
ld de,DHCP_T1+1
ld bc,12-1
ld (hl),0
ldir
;* Guarda el campo 'yiaddr' como la IP asignada,
; a no ser que hubieramos enviado DHCPINFORM
ld a,(DHCP_VECT)
and 1
jr z,ISDHCPACK4
ld hl,IN_BUFFER+48
ld de,BUF_IPLOCAL
ld bc,4
ldir
ld a,1
ld (DHCP_VECT_O),a
ISDHCPACK4:
;* Recorre todas las opciones y las procesa
call DHCP_INIT_OP
ISDHCPACKL: call DHCP_NEXT_OP
or a
jp z,ISDHCPACKEND ;No quedan opciones?
;* T1: Lo almacena
cp 58
jr nz,ISDHCPACK_NOT1
push ix
pop hl
ld de,DHCP_T1
ld bc,4
ldir
ld ix,DHCP_T1
call POR60_32
jr ISDHCPACKL
ISDHCPACK_NOT1:
;* T2: Lo almacena
cp 59
jr nz,ISDHCPACK_NOT2
push ix
pop hl
ld de,DHCP_T2
ld bc,4
ldir
ld ix,DHCP_T2
call POR60_32
jr ISDHCPACKL
ISDHCPACK_NOT2:
;* Lease: Lo almacena
cp 51
jr nz,ISDHCPACK_NOLS
push ix
pop hl
ld de,DHCP_LEASE
ld bc,4
ldir
ld ix,DHCP_LEASE
call POR60_32
jr ISDHCPACKL
ISDHCPACK_NOLS:
;* Mascara de subred: la almacena si la habiamos pedido
cp 1
jr nz,ISDHCPACK_NOSB
ld a,(DHCP_VECT)
and %10 ;La habiamos pedido?
jr z,ISDHCPACKL
push ix
pop hl
ld de,SUBNET_MASK
ld bc,4
ldir
ld a,(DHCP_VECT_O)
or %10
ld (DHCP_VECT_O),a
jr ISDHCPACKL
ISDHCPACK_NOSB:
;* Gateway por defecto: lo almacena si lo habiamos pedido
cp 3
jr nz,ISDHCPACK_NOGW
ld a,(DHCP_VECT)
and %100 ;La habiamos pedido?
jr z,ISDHCPACKL
push ix
pop hl
ld de,DEFGW
ld bc,4
ldir
ld a,(DHCP_VECT_O)
or %100
ld (DHCP_VECT_O),a
jp ISDHCPACKL
ISDHCPACK_NOGW:
;* Servidores DNS: los almacena si los habiamos pedido
cp 6
jr nz,ISDHCPACK_NODN
ld a,(DHCP_VECT)
and %1000 ;Los habiamos pedido?
jp z,ISDHCPACKL
ld a,(DHCP_VECT_O)
or %1000
ld (DHCP_VECT_O),a
push bc
push ix
pop hl
ld de,BUF_IPDNS1
ld bc,4
ldir
pop bc ;Hay mas de un DNS en la opcion?
ld a,b
cp 8
jp c,ISDHCPACKL
ld de,BUF_IPDNS2
ld bc,4
ldir
jp ISDHCPACKL
ISDHCPACK_NODN:
;* Timeout ARP: lo almacena si lo habiamos pedido
cp 35
jr nz,ISDHCPACK_NOAT
ld a,(DHCP_VECT)
and %10000 ;Lo habiamos pedido?
jp z,ISDHCPACKL
push ix,ix
pop hl
ld de,ARP_TOUT
ld bc,4
ldir
pop hl
ld de,ARP_TOUT_SECS
ld bc,4
ldir
ld ix,ARP_TOUT
call POR60_32
ld a,(DHCP_VECT_O)
or %10000
ld (DHCP_VECT_O),a
jp ISDHCPACKL
ISDHCPACK_NOAT:
;* Tipo de trama ethernet: lo almacena si lo habiamos pedido
cp 36
jr nz,ISDHCPACK_NOFT
ld a,(DHCP_VECT)
and %100000 ;Lo habiamos pedido?
jp z,ISDHCPACKL
ld a,(ix)
or a
jr z,ISDHCPACK_FT
ld a,#FF
ISDHCPACK_FT: ld (FRAME_TYPE),a
ld a,(DHCP_VECT_O)
or %100000
ld (DHCP_VECT_O),a
;jp ISDHCPACKL
ISDHCPACK_NOFT:
;* Opcion no reconocida: ignorarla
jp ISDHCPACKL
ISDHCPACKEND:
;* Fin de las opciones.
; Si estamos en INFORMING, pasar a CONFIGURED y terminar.
ld a,(DHCP_STATE)
cp INFORMING
jr nz,ISDHCPACKEND0
ld a,CONFIGURED
ld (DHCP_STATE),a
jp END_GET_PACK
ISDHCPACKEND0:
;* Si T1 es 0, establecerlo a lease/2
ld hl,DHCP_T1
ld de,ZERO32
call COMP32
jr nz,OKT1NZ
ld hl,#FFFF ;Si lease infinito, T1 infinito
ld (DHCP_T1),hl
ld (DHCP_T1+2),hl
ld a,(DHCP_LEASE)
cp h
jr z,OKT1NZ
ld hl,DHCP_LEASE
ld de,DHCP_T1
ld bc,4
ldir
ld ix,DHCP_T1
ld b,1
call ENTRE2_32
OKT1NZ:
;* Si T2 es 0, establecerlo a 0.875*lease ((7/8)*lease)
ld hl,DHCP_T2
ld de,ZERO32
call COMP32
jr nz,OKT2NZ
ld hl,#FFFF ;Si lease infinito, T2 infinito
ld (DHCP_T2),hl
ld (DHCP_T2+2),hl
ld a,(DHCP_LEASE)
cp h
jr z,OKT2NZ
ld hl,DHCP_LEASE
ld de,DHCP_T2
ld bc,4
ldir
ld ix,DHCP_T2 ;Divide T2 entre 8
ld b,3
call ENTRE2_32
ld hl,DHCP_T2
ld de,IN_BUFFER
ld bc,4
ldir
ld b,6
T2ISZL: push bc ;Multiplica (T2/8) por 7
ld hl,IN_BUFFER
ld de,DHCP_T2
ld bc,DHCP_T2
call ADD32
pop bc
djnz T2ISZL
OKT2NZ:
;* Fin: pasa a BOUND y termina
ld a,BOUND
ld (DHCP_STATE),a
jp END_GET_PACK
;--- Paquete NAK
IS_DHCP_NAK:
;* En estado BOUND, SELECTING, INFORMING o CONFIGURED, ignorarlo
ld a,(DHCP_STATE)
cp BOUND
jp z,END_GET_PACK
cp SELECTING
jp z,END_GET_PACK
cp INFORMING
jp z,END_GET_PACK
cp CONFIGURED
jp z,END_GET_PACK
;* En otros estados, volver a INIT
xor a ;ld a,INIT
ld (DHCP_STATE),a
jp END_GET_PACK
;===============================
;=== Segmento TCP recibido ===
;===============================
;Despues de la publicidad.
NOTA: Si no sabes qué es esto, no eres un friki auténtico. Háztelo mirar.
22 mayo 2007
¿Coincidencia? No lo creo...
Se abre el telón y estamos a domingo 20 de mayo. El friki me llama por fonófono para decirme que ponga la tele, pues en cierto canal están emitiendo un programa en el que aparece Parque España, un pintoresco lugar de Japón sobre el que ya escribí algo. Nos echamos unas risas y se cierra el telón.
Se vuelve a abrir el telón y estamos a martes 22 de mayo. Me da por comprobar las palabras que la gente estaba buscando cuando encontró mi blog, y me encuentro esto:

Se cierra el telón y pregunto: ¿seguro que la gente ya no ve tanto la tele por culpa del interdem?
Se vuelve a abrir el telón y estamos a martes 22 de mayo. Me da por comprobar las palabras que la gente estaba buscando cuando encontró mi blog, y me encuentro esto:
Se cierra el telón y pregunto: ¿seguro que la gente ya no ve tanto la tele por culpa del interdem?
17 mayo 2007
Especial Kaito
En esta ocasión voy a llevar a cabo un experimento blogológico: una entrada sin texto, sólo con fotos y pies de idem. Así pus, olvida que has leído esta frase, y deléitate con el siguiente batiburrillo de píxeles coloreados a mayor gloria del señor Soriano Koizumi.
- ¡Teneis que creerme! ¡Era una visión horrible! ¡De verdad, he visto a mi padre desnudo! ¡¡No estoy loco, maldita sea!!
- ¡Teneis que creerme! ¡Era una visión horrible! ¡De verdad, he visto a mi padre desnudo! ¡¡No estoy loco, maldita sea!!
Suscribirse a:
Entradas (Atom)








































